From 4b67f639061911f07442f05484114f0c4cddc64e Mon Sep 17 00:00:00 2001 From: Leonard Kugis Date: Sun, 9 Apr 2023 05:40:53 +0200 Subject: Implemented metadata tagging --- file-tagger.py | 25 +++++++++++++++++++++++++ gui.py | 37 ++++++++++++++++++++----------------- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/file-tagger.py b/file-tagger.py index 9708dfa..67e1102 100644 --- a/file-tagger.py +++ b/file-tagger.py @@ -9,6 +9,7 @@ from tmsu import * from util import * from predictor import * from PIL import Image +import datetime ''' Walk over all files for the given base directory and all subdirectories recursively. @@ -54,6 +55,28 @@ def walk(tmsu, args): if args["open_system"]: open_system(file_path) + if args["tag_metadata"]: + # Base name and extension + base = os.path.splitext(os.path.basename(file_path)) + if base[1]: + tags.update({base[0], base[1]}) + else: + tags.update({base[0]}) + # File creation and modification time + time_c = datetime.datetime.fromtimestamp(os.path.getctime(file_path)) + time_m = datetime.datetime.fromtimestamp(os.path.getmtime(file_path)) + tags.update({time_c.strftime("%Y-%m-%d"), + time_c.strftime("%Y"), + time_c.strftime("%B"), + time_c.strftime("%A"), + time_c.strftime("%Hh")}) + if time_c != time_m: + tags.update({time_m.strftime("%Y-%m-%d"), + time_m.strftime("%Y"), + time_m.strftime("%B"), + time_m.strftime("%A"), + time_m.strftime("%Hh")}) + # Detect MIME-type for file mime_type = mime.from_file(file_path) @@ -106,6 +129,7 @@ if __name__ == "__main__": parser.add_argument('-f', '--file-dir', nargs='?', default='.', type=dir_path, help='File directory for walking (default: %(default)s)') parser.add_argument('-g', '--gui', nargs='?', const=1, default=False, type=bool, help='Show main GUI (default: %(default)s)') parser.add_argument('--tmsu-command', nargs='?', const=1, default="tmsu", type=str, help='TMSU command override (default: %(default)s)') + parser.add_argument('--tag-metadata', nargs='?', const=1, default=True, type=bool, help='Use metadata as default tags (default: %(default)s)') parser.add_argument('--predict-images', nargs='?', const=1, default=False, type=bool, help='Use prediction for image tagging (default: %(default)s)') parser.add_argument('--predict-images-backend', nargs='?', const=1, choices=["torch", "tensorflow", "keras"], default="torch", type=str.lower, help='Determines which backend should be used for keyword prediction (default: %(default)s)') parser.add_argument('--predict-images-top', nargs='?', const=1, default=10, type=int, help='Defines how many top prediction keywords should be used (default: %(default)s)') @@ -135,6 +159,7 @@ if __name__ == "__main__": "file_dir": args.file_dir, "gui": args.gui, "tmsu_command": args.tmsu_command, + "tag_metadata": args.tag_metadata, "predict_images": args.predict_images, "predict_images_backend": args.predict_images_backend, "predict_images_top": args.predict_images_top, diff --git a/gui.py b/gui.py index 7bd30ad..8f2ad4c 100644 --- a/gui.py +++ b/gui.py @@ -13,6 +13,7 @@ class GuiMain(object): self.__args = args self.__base = StringVar(self.__master, value=args["base"]) self.__file_dir = StringVar(self.__master, value=args["file_dir"]) + self.__tag_metadata = BooleanVar(self.__master, value=args["tag_metadata"]) self.__predict_images = BooleanVar(self.__master, value=args["predict_images"]) self.__predict_images_backend = StringVar(self.__master, value=str(args["predict_images_backend"])) self.__predict_images_top = StringVar(self.__master, value=str(args["predict_images_top"])) @@ -33,29 +34,31 @@ class GuiMain(object): Label(self.__master, text="File directory for walking:").grid(row=1, column=0) Entry(self.__master, textvariable=self.__file_dir).grid(row=1, column=1, columnspan=2) Button(self.__master, text="Browse", command=lambda: self.__browse(self.__file_dir)).grid(row=1, column=3) - Checkbutton(self.__master, text="Use prediction for image tagging", variable=self.__predict_images).grid(row=2, column=0, columnspan=4, sticky=W) - Label(self.__master, text="Image prediction backend:").grid(row=3, column=0) - ttk.Combobox(self.__master, textvariable=self.__predict_images_backend, values=("torch", "tensorflow", "keras"), state="readonly").grid(row=3, column=1) - Label(self.__master, text="Number of top results:").grid(row=4, column=0) - Entry(self.__master, textvariable=self.__predict_images_top, validate='all', validatecommand=(validate_number, '%P')).grid(row=4, column=1, columnspan=1) - Checkbutton(self.__master, text="Skip detail scan in image prediction", variable=self.__predict_images_skip_detail).grid(row=5, column=0, columnspan=4, sticky=W) - Label(self.__master, text="Width factor for detail scan:").grid(row=6, column=0) - Entry(self.__master, textvariable=self.__predict_images_detail_factor, validate='all', validatecommand=(validate_number, '%P')).grid(row=6, column=1, columnspan=1) - Checkbutton(self.__master, text="Show GUI for tagging", variable=self.__gui_tag).grid(row=7, column=0, columnspan=4, sticky=W) - Label(self.__master, text="Image GUI preview size:").grid(row=8, column=0) - Entry(self.__master, textvariable=self.__gui_image_length, validate='all', validatecommand=(validate_number, '%P')).grid(row=8, column=1, columnspan=1) - Checkbutton(self.__master, text="Open all files with system default", variable=self.__open_system).grid(row=9, column=0, columnspan=4, sticky=W) - Checkbutton(self.__master, text="Skip prompt for file tags", variable=self.__skip_prompt).grid(row=10, column=0, columnspan=4, sticky=W) - Checkbutton(self.__master, text="Skip already tagged files", variable=self.__skip_tagged).grid(row=11, column=0, columnspan=4, sticky=W) - Label(self.__master, text="Start at index:").grid(row=12, column=0) - Entry(self.__master, textvariable=self.__index, validate='all', validatecommand=(validate_number, '%P')).grid(row=12, column=1, columnspan=1) - Button(self.__master, text="Start", command=self.__master.destroy).grid(row=13, column=0, columnspan=4) + Checkbutton(self.__master, text="Use metadata as default tags", variable=self.__tag_metadata).grid(row=2, column=0, columnspan=4, sticky=W) + Checkbutton(self.__master, text="Use prediction for image tagging", variable=self.__predict_images).grid(row=3, column=0, columnspan=4, sticky=W) + Label(self.__master, text="Image prediction backend:").grid(row=4, column=0) + ttk.Combobox(self.__master, textvariable=self.__predict_images_backend, values=("torch", "tensorflow", "keras"), state="readonly").grid(row=4, column=1) + Label(self.__master, text="Number of top results:").grid(row=5, column=0) + Entry(self.__master, textvariable=self.__predict_images_top, validate='all', validatecommand=(validate_number, '%P')).grid(row=5, column=1, columnspan=1) + Checkbutton(self.__master, text="Skip detail scan in image prediction", variable=self.__predict_images_skip_detail).grid(row=6, column=0, columnspan=4, sticky=W) + Label(self.__master, text="Width factor for detail scan:").grid(row=7, column=0) + Entry(self.__master, textvariable=self.__predict_images_detail_factor, validate='all', validatecommand=(validate_number, '%P')).grid(row=7, column=1, columnspan=1) + Checkbutton(self.__master, text="Show GUI for tagging", variable=self.__gui_tag).grid(row=8, column=0, columnspan=4, sticky=W) + Label(self.__master, text="Image GUI preview size:").grid(row=9, column=0) + Entry(self.__master, textvariable=self.__gui_image_length, validate='all', validatecommand=(validate_number, '%P')).grid(row=9, column=1, columnspan=1) + Checkbutton(self.__master, text="Open all files with system default", variable=self.__open_system).grid(row=10, column=0, columnspan=4, sticky=W) + Checkbutton(self.__master, text="Skip prompt for file tags", variable=self.__skip_prompt).grid(row=11, column=0, columnspan=4, sticky=W) + Checkbutton(self.__master, text="Skip already tagged files", variable=self.__skip_tagged).grid(row=12, column=0, columnspan=4, sticky=W) + Label(self.__master, text="Start at index:").grid(row=13, column=0) + Entry(self.__master, textvariable=self.__index, validate='all', validatecommand=(validate_number, '%P')).grid(row=13, column=1, columnspan=1) + Button(self.__master, text="Start", command=self.__master.destroy).grid(row=14, column=0, columnspan=4) def loop(self): self.__master.mainloop() self.__args["base"] = self.__base.get() self.__args["file_dir"] = self.__file_dir.get() + self.__args["tag_metadata"] = self.__tag_metadata.get() self.__args["predict_images"] = self.__predict_images.get() self.__args["predict_images_backend"] = self.__predict_images_backend.get() self.__args["predict_images_top"] = int(self.__predict_images_top.get()) -- cgit v1.2.1