From ba16735f280f9c3e43f8bee5dfc34b7196f76a95 Mon Sep 17 00:00:00 2001 From: Creepybits Date: Sun, 16 Nov 2025 09:54:06 +0100 Subject: [PATCH 1/5] Add files via upload Added logic for automatically set .json extension to new databases --- clipvision_db.py | 113 ++++++++++------------------------------------- 1 file changed, 24 insertions(+), 89 deletions(-) diff --git a/clipvision_db.py b/clipvision_db.py index b702012..fe931be 100644 --- a/clipvision_db.py +++ b/clipvision_db.py @@ -4,8 +4,6 @@ import orjson from .utils import (generate_clip_features_json) -import fnmatch -import time class LoadDB: """ @@ -22,18 +20,17 @@ def __init__(self): @classmethod def INPUT_TYPES(s): - return { - "required": { + return { + "required": { "db_name": (folder_paths.get_filename_list("EmbDBs"),) , "path_to_images_folder": ("STRING", { "multiline": False, - "default": "/path/to/folder/with/images", - "tooltip": "Basepath to the folder containing the images" - }), + "default": "/path/to/folder/with/images" + }), }, "optional": { "img_db": ("LoadDB",), - } + } } RETURN_TYPES = ("LoadDB", ) @@ -52,7 +49,7 @@ def load_DB(self, db_name, path_to_images_folder, img_db=None): Returns: A LoadDB object. - """ + """ db_path = folder_paths.get_full_path_or_raise("EmbDBs", db_name) if self.LOADED_DB_Name != db_path or path_to_images_folder != self.images_folder: try: @@ -68,109 +65,42 @@ def load_DB(self, db_name, path_to_images_folder, img_db=None): except Exception as e: print(f"Error loading database file: {e}") return None, - + if img_db is not None: self.LOADED_DB = self.MY_LOADED_DB + img_db.LOADED_DB else: self.LOADED_DB = self.MY_LOADED_DB - return self, - -class EditDB: - - MY_LOADED_DB: list = None - LOADED_DB: list = None - LOADED_DB_Name = "" - images_folder = "" - - def __init__(self): - pass - - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "img_db": ("LoadDB",), - "method": (["exclude", "filter", "replace"], {"default": "exclude", "tooltip": "Method to edit results"}), - "edit_text": ("STRING", { - "multiline": False, - "default": "remove*images.jpg", - "tooltip": "Use wildcards (*) to match filenames or paths" - },), - "replace_text": ("STRING", { - "multiline": False, - "default": "/newpath/", - "tooltip": "Text to replace matched text with when using 'replace' method" - },), - } - } - - RETURN_TYPES = ("LoadDB", ) - RETURN_NAMES = ("IMG_DB", ) - FUNCTION = "Edit_DB" - CATEGORY = "ClipVisionTools" - - def Edit_DB(self, img_db:LoadDB, method, edit_text, replace_text): - NewDB = LoadDB() - NewDB.LOADED_DB = [] - - if isinstance(edit_text, str): - edit_text = [edit_text] - - for file_name, embeddings in img_db.LOADED_DB: - if method == "exclude": - if not any(fnmatch.fnmatch(file_name, pat) for pat in edit_text): - NewDB.LOADED_DB.append((file_name, embeddings)) - - if method == "filter": - if any(fnmatch.fnmatch(file_name, pat) for pat in edit_text): - NewDB.LOADED_DB.append((file_name, embeddings)) - - if method == "replace": - new_name = file_name - for pat in edit_text: - if fnmatch.fnmatch(file_name, pat): - new_name = file_name.replace(pat.strip("*"), replace_text) - NewDB.LOADED_DB.append((new_name, embeddings)) - - return NewDB, + return self, class GenerateDB: """ Generates a new image database from a folder of images. """ - last_error: bool = True - last_time: float = 0.0 - def __init__(self): pass @classmethod def INPUT_TYPES(s): return { - "required": { + "required": { "clip_vision": ("CLIP_VISION",), "path_to_images_folder": ("STRING", { "multiline": False, - "default": "path/to/folder/with/images", - "tooltip": "Basepath to the folder containing the images" + "default": "path/to/folder/with/images" }), "new_db_name": ("STRING", { "multiline": False, - "default": "new_img_db.json", - "tooltip": "Name of the new database file to create" + "default": "new_img_db.json" }), - }, - "hidden": { - "unique_id": "UNIQUE_ID", } } - + RETURN_TYPES = ("STRING",) RETURN_NAMES = ("ERRORS",) OUTPUT_NODE = True FUNCTION = "start_gen_db" CATEGORY = "ClipVisionTools" - def start_gen_db(self, clip_vision, path_to_images_folder, new_db_name, unique_id): + def start_gen_db(self, clip_vision, path_to_images_folder, new_db_name): """ Generates a new image database. @@ -181,13 +111,18 @@ def start_gen_db(self, clip_vision, path_to_images_folder, new_db_name, unique_i Returns: A string containing any errors that occurred. - """ + """ + # Make sure the database name ends with .json + if not new_db_name.endswith('.json'): + new_db_name += '.json' + path_to_images = Path(path_to_images_folder) path_to_database = Path(folder_paths.get_folder_paths("EmbDBs")[0]) / new_db_name - + path_to_database.parent.mkdir(exist_ok=True) - - errors = generate_clip_features_json(clip_vision, path_to_images, path_to_database, unique_id) - return errors, - + try: + errors = generate_clip_features_json(clip_vision, path_to_images, path_to_database) + return errors, + except Exception as e: + return f"Error generating database file: {e}" From 07e7144f0c948e0e61b63cdb547e04e6d43fa5b2 Mon Sep 17 00:00:00 2001 From: Creepybits Date: Sun, 16 Nov 2025 09:57:51 +0100 Subject: [PATCH 2/5] Update clipvision_db.py --- clipvision_db.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clipvision_db.py b/clipvision_db.py index fe931be..d4269b8 100644 --- a/clipvision_db.py +++ b/clipvision_db.py @@ -4,6 +4,8 @@ import orjson from .utils import (generate_clip_features_json) +import fnmatch +import time class LoadDB: """ @@ -126,3 +128,4 @@ def start_gen_db(self, clip_vision, path_to_images_folder, new_db_name): return errors, except Exception as e: return f"Error generating database file: {e}" + From 1cd615b51f29c39260b104b58021e75f8f4913dd Mon Sep 17 00:00:00 2001 From: Creepybits Date: Sun, 16 Nov 2025 10:12:13 +0100 Subject: [PATCH 3/5] Add files via upload Added logic to automatically set .json extention to new databases --- clipvision_db.py | 84 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/clipvision_db.py b/clipvision_db.py index d4269b8..b29e2ca 100644 --- a/clipvision_db.py +++ b/clipvision_db.py @@ -27,7 +27,8 @@ def INPUT_TYPES(s): "db_name": (folder_paths.get_filename_list("EmbDBs"),) , "path_to_images_folder": ("STRING", { "multiline": False, - "default": "/path/to/folder/with/images" + "default": "/path/to/folder/with/images", + "tooltip": "Basepath to the folder containing the images" }), }, "optional": { @@ -74,10 +75,72 @@ def load_DB(self, db_name, path_to_images_folder, img_db=None): self.LOADED_DB = self.MY_LOADED_DB return self, +class EditDB: + + MY_LOADED_DB: list = None + LOADED_DB: list = None + LOADED_DB_Name = "" + images_folder = "" + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "img_db": ("LoadDB",), + "method": (["exclude", "filter", "replace"], {"default": "exclude", "tooltip": "Method to edit results"}), + "edit_text": ("STRING", { + "multiline": False, + "default": "remove*images.jpg", + "tooltip": "Use wildcards (*) to match filenames or paths" + },), + "replace_text": ("STRING", { + "multiline": False, + "default": "/newpath/", + "tooltip": "Text to replace matched text with when using 'replace' method" + },), + } + } + + RETURN_TYPES = ("LoadDB", ) + RETURN_NAMES = ("IMG_DB", ) + FUNCTION = "Edit_DB" + CATEGORY = "ClipVisionTools" + + def Edit_DB(self, img_db:LoadDB, method, edit_text, replace_text): + NewDB = LoadDB() + NewDB.LOADED_DB = [] + + if isinstance(edit_text, str): + edit_text = [edit_text] + + for file_name, embeddings in img_db.LOADED_DB: + if method == "exclude": + if not any(fnmatch.fnmatch(file_name, pat) for pat in edit_text): + NewDB.LOADED_DB.append((file_name, embeddings)) + + if method == "filter": + if any(fnmatch.fnmatch(file_name, pat) for pat in edit_text): + NewDB.LOADED_DB.append((file_name, embeddings)) + + if method == "replace": + new_name = file_name + for pat in edit_text: + if fnmatch.fnmatch(file_name, pat): + new_name = file_name.replace(pat.strip("*"), replace_text) + NewDB.LOADED_DB.append((new_name, embeddings)) + + return NewDB, + class GenerateDB: """ Generates a new image database from a folder of images. """ + last_error: bool = True + last_time: float = 0.0 + def __init__(self): pass @classmethod @@ -87,12 +150,17 @@ def INPUT_TYPES(s): "clip_vision": ("CLIP_VISION",), "path_to_images_folder": ("STRING", { "multiline": False, - "default": "path/to/folder/with/images" + "default": "path/to/folder/with/images", + "tooltip": "Basepath to the folder containing the images" }), "new_db_name": ("STRING", { "multiline": False, - "default": "new_img_db.json" + "default": "new_img_db.json", + "tooltip": "Name of the new database file to create" }), + }, + "hidden": { + "unique_id": "UNIQUE_ID", } } @@ -102,7 +170,7 @@ def INPUT_TYPES(s): FUNCTION = "start_gen_db" CATEGORY = "ClipVisionTools" - def start_gen_db(self, clip_vision, path_to_images_folder, new_db_name): + def start_gen_db(self, clip_vision, path_to_images_folder, new_db_name, unique_id): """ Generates a new image database. @@ -123,9 +191,5 @@ def start_gen_db(self, clip_vision, path_to_images_folder, new_db_name): path_to_database.parent.mkdir(exist_ok=True) - try: - errors = generate_clip_features_json(clip_vision, path_to_images, path_to_database) - return errors, - except Exception as e: - return f"Error generating database file: {e}" - + errors = generate_clip_features_json(clip_vision, path_to_images, path_to_database, unique_id) + return errors, From 9d4ca63660f54d4ad9829d98d43cd1ace344116e Mon Sep 17 00:00:00 2001 From: Creepybits Date: Sun, 16 Nov 2025 10:17:41 +0100 Subject: [PATCH 4/5] Add files via upload --- clipvision_db.py | 390 +++++++++++++++++++++++------------------------ 1 file changed, 195 insertions(+), 195 deletions(-) diff --git a/clipvision_db.py b/clipvision_db.py index b29e2ca..3ba17ad 100644 --- a/clipvision_db.py +++ b/clipvision_db.py @@ -1,195 +1,195 @@ -import os -from pathlib import Path -import folder_paths -import orjson - -from .utils import (generate_clip_features_json) -import fnmatch -import time - -class LoadDB: - """ - Loads an image database from a JSON file. - """ - - MY_LOADED_DB: list = None - LOADED_DB: list = None - LOADED_DB_Name = "" - images_folder = "" - - def __init__(self): - pass - - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "db_name": (folder_paths.get_filename_list("EmbDBs"),) , - "path_to_images_folder": ("STRING", { - "multiline": False, - "default": "/path/to/folder/with/images", - "tooltip": "Basepath to the folder containing the images" - }), - }, - "optional": { - "img_db": ("LoadDB",), - } - } - - RETURN_TYPES = ("LoadDB", ) - RETURN_NAMES = ("IMG_DB", ) - FUNCTION = "load_DB" - CATEGORY = "ClipVisionTools" - - def load_DB(self, db_name, path_to_images_folder, img_db=None): - """ - Loads the image database from the specified JSON file. - - Args: - db_name: The name of the database file. - path_to_images_folder: The path to the folder containing the images. - img_db: An optional existing LoadDB object to append to. - - Returns: - A LoadDB object. - """ - db_path = folder_paths.get_full_path_or_raise("EmbDBs", db_name) - if self.LOADED_DB_Name != db_path or path_to_images_folder != self.images_folder: - try: - with open(db_path, "rb") as f: - data = orjson.loads(f.read()) - - self.MY_LOADED_DB = [ - (os.path.join(path_to_images_folder, filename), vector) - for filename, vector in data - ] - self.LOADED_DB_Name = db_path - self.images_folder = path_to_images_folder - except Exception as e: - print(f"Error loading database file: {e}") - return None, - - if img_db is not None: - self.LOADED_DB = self.MY_LOADED_DB + img_db.LOADED_DB - else: - self.LOADED_DB = self.MY_LOADED_DB - return self, - -class EditDB: - - MY_LOADED_DB: list = None - LOADED_DB: list = None - LOADED_DB_Name = "" - images_folder = "" - - def __init__(self): - pass - - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "img_db": ("LoadDB",), - "method": (["exclude", "filter", "replace"], {"default": "exclude", "tooltip": "Method to edit results"}), - "edit_text": ("STRING", { - "multiline": False, - "default": "remove*images.jpg", - "tooltip": "Use wildcards (*) to match filenames or paths" - },), - "replace_text": ("STRING", { - "multiline": False, - "default": "/newpath/", - "tooltip": "Text to replace matched text with when using 'replace' method" - },), - } - } - - RETURN_TYPES = ("LoadDB", ) - RETURN_NAMES = ("IMG_DB", ) - FUNCTION = "Edit_DB" - CATEGORY = "ClipVisionTools" - - def Edit_DB(self, img_db:LoadDB, method, edit_text, replace_text): - NewDB = LoadDB() - NewDB.LOADED_DB = [] - - if isinstance(edit_text, str): - edit_text = [edit_text] - - for file_name, embeddings in img_db.LOADED_DB: - if method == "exclude": - if not any(fnmatch.fnmatch(file_name, pat) for pat in edit_text): - NewDB.LOADED_DB.append((file_name, embeddings)) - - if method == "filter": - if any(fnmatch.fnmatch(file_name, pat) for pat in edit_text): - NewDB.LOADED_DB.append((file_name, embeddings)) - - if method == "replace": - new_name = file_name - for pat in edit_text: - if fnmatch.fnmatch(file_name, pat): - new_name = file_name.replace(pat.strip("*"), replace_text) - NewDB.LOADED_DB.append((new_name, embeddings)) - - return NewDB, - -class GenerateDB: - """ - Generates a new image database from a folder of images. - """ - last_error: bool = True - last_time: float = 0.0 - - def __init__(self): - pass - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "clip_vision": ("CLIP_VISION",), - "path_to_images_folder": ("STRING", { - "multiline": False, - "default": "path/to/folder/with/images", - "tooltip": "Basepath to the folder containing the images" - }), - "new_db_name": ("STRING", { - "multiline": False, - "default": "new_img_db.json", - "tooltip": "Name of the new database file to create" - }), - }, - "hidden": { - "unique_id": "UNIQUE_ID", - } - } - - RETURN_TYPES = ("STRING",) - RETURN_NAMES = ("ERRORS",) - OUTPUT_NODE = True - - FUNCTION = "start_gen_db" - CATEGORY = "ClipVisionTools" - def start_gen_db(self, clip_vision, path_to_images_folder, new_db_name, unique_id): - """ - Generates a new image database. - - Args: - clip_vision: The CLIP vision object. - path_to_images_folder: The path to the folder containing the images. - new_db_name: The name of the new database file. - - Returns: - A string containing any errors that occurred. - """ - # Make sure the database name ends with .json - if not new_db_name.endswith('.json'): - new_db_name += '.json' - - path_to_images = Path(path_to_images_folder) - path_to_database = Path(folder_paths.get_folder_paths("EmbDBs")[0]) / new_db_name - - path_to_database.parent.mkdir(exist_ok=True) - - errors = generate_clip_features_json(clip_vision, path_to_images, path_to_database, unique_id) - return errors, +import os +from pathlib import Path +import folder_paths +import orjson + +from .utils import (generate_clip_features_json) +import fnmatch +import time + +class LoadDB: + """ + Loads an image database from a JSON file. + """ + + MY_LOADED_DB: list = None + LOADED_DB: list = None + LOADED_DB_Name = "" + images_folder = "" + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "db_name": (folder_paths.get_filename_list("EmbDBs"),) , + "path_to_images_folder": ("STRING", { + "multiline": False, + "default": "/path/to/folder/with/images", + "tooltip": "Basepath to the folder containing the images" + }), + }, + "optional": { + "img_db": ("LoadDB",), + } + } + + RETURN_TYPES = ("LoadDB", ) + RETURN_NAMES = ("IMG_DB", ) + FUNCTION = "load_DB" + CATEGORY = "ClipVisionTools" + + def load_DB(self, db_name, path_to_images_folder, img_db=None): + """ + Loads the image database from the specified JSON file. + + Args: + db_name: The name of the database file. + path_to_images_folder: The path to the folder containing the images. + img_db: An optional existing LoadDB object to append to. + + Returns: + A LoadDB object. + """ + db_path = folder_paths.get_full_path_or_raise("EmbDBs", db_name) + if self.LOADED_DB_Name != db_path or path_to_images_folder != self.images_folder: + try: + with open(db_path, "rb") as f: + data = orjson.loads(f.read()) + + self.MY_LOADED_DB = [ + (os.path.join(path_to_images_folder, filename), vector) + for filename, vector in data + ] + self.LOADED_DB_Name = db_path + self.images_folder = path_to_images_folder + except Exception as e: + print(f"Error loading database file: {e}") + return None, + + if img_db is not None: + self.LOADED_DB = self.MY_LOADED_DB + img_db.LOADED_DB + else: + self.LOADED_DB = self.MY_LOADED_DB + return self, + +class EditDB: + + MY_LOADED_DB: list = None + LOADED_DB: list = None + LOADED_DB_Name = "" + images_folder = "" + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "img_db": ("LoadDB",), + "method": (["exclude", "filter", "replace"], {"default": "exclude", "tooltip": "Method to edit results"}), + "edit_text": ("STRING", { + "multiline": False, + "default": "remove*images.jpg", + "tooltip": "Use wildcards (*) to match filenames or paths" + },), + "replace_text": ("STRING", { + "multiline": False, + "default": "/newpath/", + "tooltip": "Text to replace matched text with when using 'replace' method" + },), + } + } + + RETURN_TYPES = ("LoadDB", ) + RETURN_NAMES = ("IMG_DB", ) + FUNCTION = "Edit_DB" + CATEGORY = "ClipVisionTools" + + def Edit_DB(self, img_db:LoadDB, method, edit_text, replace_text): + NewDB = LoadDB() + NewDB.LOADED_DB = [] + + if isinstance(edit_text, str): + edit_text = [edit_text] + + for file_name, embeddings in img_db.LOADED_DB: + if method == "exclude": + if not any(fnmatch.fnmatch(file_name, pat) for pat in edit_text): + NewDB.LOADED_DB.append((file_name, embeddings)) + + if method == "filter": + if any(fnmatch.fnmatch(file_name, pat) for pat in edit_text): + NewDB.LOADED_DB.append((file_name, embeddings)) + + if method == "replace": + new_name = file_name + for pat in edit_text: + if fnmatch.fnmatch(file_name, pat): + new_name = file_name.replace(pat.strip("*"), replace_text) + NewDB.LOADED_DB.append((new_name, embeddings)) + + return NewDB, + +class GenerateDB: + """ + Generates a new image database from a folder of images. + """ + last_error: bool = True + last_time: float = 0.0 + + def __init__(self): + pass + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "clip_vision": ("CLIP_VISION",), + "path_to_images_folder": ("STRING", { + "multiline": False, + "default": "path/to/folder/with/images", + "tooltip": "Basepath to the folder containing the images" + }), + "new_db_name": ("STRING", { + "multiline": False, + "default": "new_img_db.json", + "tooltip": "Name of the new database file to create" + }), + }, + "hidden": { + "unique_id": "UNIQUE_ID", + } + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("ERRORS",) + OUTPUT_NODE = True + + FUNCTION = "start_gen_db" + CATEGORY = "ClipVisionTools" + def start_gen_db(self, clip_vision, path_to_images_folder, new_db_name, unique_id): + """ + Generates a new image database. + + Args: + clip_vision: The CLIP vision object. + path_to_images_folder: The path to the folder containing the images. + new_db_name: The name of the new database file. + + Returns: + A string containing any errors that occurred. + """ + # Make sure the database name ends with .json + if not new_db_name.endswith('.json'): + new_db_name += '.json' + + path_to_images = Path(path_to_images_folder) + path_to_database = Path(folder_paths.get_folder_paths("EmbDBs")[0]) / new_db_name + + path_to_database.parent.mkdir(exist_ok=True) + + errors = generate_clip_features_json(clip_vision, path_to_images, path_to_database, unique_id) + return errors, From e6ac4f8e4037697ed989e87c01a5c9fc70242471 Mon Sep 17 00:00:00 2001 From: Creepybits Date: Sun, 16 Nov 2025 10:20:09 +0100 Subject: [PATCH 5/5] Add files via upload --- clipvision_db.py | 390 +++++++++++++++++++++++------------------------ 1 file changed, 195 insertions(+), 195 deletions(-) diff --git a/clipvision_db.py b/clipvision_db.py index 3ba17ad..b29e2ca 100644 --- a/clipvision_db.py +++ b/clipvision_db.py @@ -1,195 +1,195 @@ -import os -from pathlib import Path -import folder_paths -import orjson - -from .utils import (generate_clip_features_json) -import fnmatch -import time - -class LoadDB: - """ - Loads an image database from a JSON file. - """ - - MY_LOADED_DB: list = None - LOADED_DB: list = None - LOADED_DB_Name = "" - images_folder = "" - - def __init__(self): - pass - - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "db_name": (folder_paths.get_filename_list("EmbDBs"),) , - "path_to_images_folder": ("STRING", { - "multiline": False, - "default": "/path/to/folder/with/images", - "tooltip": "Basepath to the folder containing the images" - }), - }, - "optional": { - "img_db": ("LoadDB",), - } - } - - RETURN_TYPES = ("LoadDB", ) - RETURN_NAMES = ("IMG_DB", ) - FUNCTION = "load_DB" - CATEGORY = "ClipVisionTools" - - def load_DB(self, db_name, path_to_images_folder, img_db=None): - """ - Loads the image database from the specified JSON file. - - Args: - db_name: The name of the database file. - path_to_images_folder: The path to the folder containing the images. - img_db: An optional existing LoadDB object to append to. - - Returns: - A LoadDB object. - """ - db_path = folder_paths.get_full_path_or_raise("EmbDBs", db_name) - if self.LOADED_DB_Name != db_path or path_to_images_folder != self.images_folder: - try: - with open(db_path, "rb") as f: - data = orjson.loads(f.read()) - - self.MY_LOADED_DB = [ - (os.path.join(path_to_images_folder, filename), vector) - for filename, vector in data - ] - self.LOADED_DB_Name = db_path - self.images_folder = path_to_images_folder - except Exception as e: - print(f"Error loading database file: {e}") - return None, - - if img_db is not None: - self.LOADED_DB = self.MY_LOADED_DB + img_db.LOADED_DB - else: - self.LOADED_DB = self.MY_LOADED_DB - return self, - -class EditDB: - - MY_LOADED_DB: list = None - LOADED_DB: list = None - LOADED_DB_Name = "" - images_folder = "" - - def __init__(self): - pass - - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "img_db": ("LoadDB",), - "method": (["exclude", "filter", "replace"], {"default": "exclude", "tooltip": "Method to edit results"}), - "edit_text": ("STRING", { - "multiline": False, - "default": "remove*images.jpg", - "tooltip": "Use wildcards (*) to match filenames or paths" - },), - "replace_text": ("STRING", { - "multiline": False, - "default": "/newpath/", - "tooltip": "Text to replace matched text with when using 'replace' method" - },), - } - } - - RETURN_TYPES = ("LoadDB", ) - RETURN_NAMES = ("IMG_DB", ) - FUNCTION = "Edit_DB" - CATEGORY = "ClipVisionTools" - - def Edit_DB(self, img_db:LoadDB, method, edit_text, replace_text): - NewDB = LoadDB() - NewDB.LOADED_DB = [] - - if isinstance(edit_text, str): - edit_text = [edit_text] - - for file_name, embeddings in img_db.LOADED_DB: - if method == "exclude": - if not any(fnmatch.fnmatch(file_name, pat) for pat in edit_text): - NewDB.LOADED_DB.append((file_name, embeddings)) - - if method == "filter": - if any(fnmatch.fnmatch(file_name, pat) for pat in edit_text): - NewDB.LOADED_DB.append((file_name, embeddings)) - - if method == "replace": - new_name = file_name - for pat in edit_text: - if fnmatch.fnmatch(file_name, pat): - new_name = file_name.replace(pat.strip("*"), replace_text) - NewDB.LOADED_DB.append((new_name, embeddings)) - - return NewDB, - -class GenerateDB: - """ - Generates a new image database from a folder of images. - """ - last_error: bool = True - last_time: float = 0.0 - - def __init__(self): - pass - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "clip_vision": ("CLIP_VISION",), - "path_to_images_folder": ("STRING", { - "multiline": False, - "default": "path/to/folder/with/images", - "tooltip": "Basepath to the folder containing the images" - }), - "new_db_name": ("STRING", { - "multiline": False, - "default": "new_img_db.json", - "tooltip": "Name of the new database file to create" - }), - }, - "hidden": { - "unique_id": "UNIQUE_ID", - } - } - - RETURN_TYPES = ("STRING",) - RETURN_NAMES = ("ERRORS",) - OUTPUT_NODE = True - - FUNCTION = "start_gen_db" - CATEGORY = "ClipVisionTools" - def start_gen_db(self, clip_vision, path_to_images_folder, new_db_name, unique_id): - """ - Generates a new image database. - - Args: - clip_vision: The CLIP vision object. - path_to_images_folder: The path to the folder containing the images. - new_db_name: The name of the new database file. - - Returns: - A string containing any errors that occurred. - """ - # Make sure the database name ends with .json - if not new_db_name.endswith('.json'): - new_db_name += '.json' - - path_to_images = Path(path_to_images_folder) - path_to_database = Path(folder_paths.get_folder_paths("EmbDBs")[0]) / new_db_name - - path_to_database.parent.mkdir(exist_ok=True) - - errors = generate_clip_features_json(clip_vision, path_to_images, path_to_database, unique_id) - return errors, +import os +from pathlib import Path +import folder_paths +import orjson + +from .utils import (generate_clip_features_json) +import fnmatch +import time + +class LoadDB: + """ + Loads an image database from a JSON file. + """ + + MY_LOADED_DB: list = None + LOADED_DB: list = None + LOADED_DB_Name = "" + images_folder = "" + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "db_name": (folder_paths.get_filename_list("EmbDBs"),) , + "path_to_images_folder": ("STRING", { + "multiline": False, + "default": "/path/to/folder/with/images", + "tooltip": "Basepath to the folder containing the images" + }), + }, + "optional": { + "img_db": ("LoadDB",), + } + } + + RETURN_TYPES = ("LoadDB", ) + RETURN_NAMES = ("IMG_DB", ) + FUNCTION = "load_DB" + CATEGORY = "ClipVisionTools" + + def load_DB(self, db_name, path_to_images_folder, img_db=None): + """ + Loads the image database from the specified JSON file. + + Args: + db_name: The name of the database file. + path_to_images_folder: The path to the folder containing the images. + img_db: An optional existing LoadDB object to append to. + + Returns: + A LoadDB object. + """ + db_path = folder_paths.get_full_path_or_raise("EmbDBs", db_name) + if self.LOADED_DB_Name != db_path or path_to_images_folder != self.images_folder: + try: + with open(db_path, "rb") as f: + data = orjson.loads(f.read()) + + self.MY_LOADED_DB = [ + (os.path.join(path_to_images_folder, filename), vector) + for filename, vector in data + ] + self.LOADED_DB_Name = db_path + self.images_folder = path_to_images_folder + except Exception as e: + print(f"Error loading database file: {e}") + return None, + + if img_db is not None: + self.LOADED_DB = self.MY_LOADED_DB + img_db.LOADED_DB + else: + self.LOADED_DB = self.MY_LOADED_DB + return self, + +class EditDB: + + MY_LOADED_DB: list = None + LOADED_DB: list = None + LOADED_DB_Name = "" + images_folder = "" + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "img_db": ("LoadDB",), + "method": (["exclude", "filter", "replace"], {"default": "exclude", "tooltip": "Method to edit results"}), + "edit_text": ("STRING", { + "multiline": False, + "default": "remove*images.jpg", + "tooltip": "Use wildcards (*) to match filenames or paths" + },), + "replace_text": ("STRING", { + "multiline": False, + "default": "/newpath/", + "tooltip": "Text to replace matched text with when using 'replace' method" + },), + } + } + + RETURN_TYPES = ("LoadDB", ) + RETURN_NAMES = ("IMG_DB", ) + FUNCTION = "Edit_DB" + CATEGORY = "ClipVisionTools" + + def Edit_DB(self, img_db:LoadDB, method, edit_text, replace_text): + NewDB = LoadDB() + NewDB.LOADED_DB = [] + + if isinstance(edit_text, str): + edit_text = [edit_text] + + for file_name, embeddings in img_db.LOADED_DB: + if method == "exclude": + if not any(fnmatch.fnmatch(file_name, pat) for pat in edit_text): + NewDB.LOADED_DB.append((file_name, embeddings)) + + if method == "filter": + if any(fnmatch.fnmatch(file_name, pat) for pat in edit_text): + NewDB.LOADED_DB.append((file_name, embeddings)) + + if method == "replace": + new_name = file_name + for pat in edit_text: + if fnmatch.fnmatch(file_name, pat): + new_name = file_name.replace(pat.strip("*"), replace_text) + NewDB.LOADED_DB.append((new_name, embeddings)) + + return NewDB, + +class GenerateDB: + """ + Generates a new image database from a folder of images. + """ + last_error: bool = True + last_time: float = 0.0 + + def __init__(self): + pass + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "clip_vision": ("CLIP_VISION",), + "path_to_images_folder": ("STRING", { + "multiline": False, + "default": "path/to/folder/with/images", + "tooltip": "Basepath to the folder containing the images" + }), + "new_db_name": ("STRING", { + "multiline": False, + "default": "new_img_db.json", + "tooltip": "Name of the new database file to create" + }), + }, + "hidden": { + "unique_id": "UNIQUE_ID", + } + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("ERRORS",) + OUTPUT_NODE = True + + FUNCTION = "start_gen_db" + CATEGORY = "ClipVisionTools" + def start_gen_db(self, clip_vision, path_to_images_folder, new_db_name, unique_id): + """ + Generates a new image database. + + Args: + clip_vision: The CLIP vision object. + path_to_images_folder: The path to the folder containing the images. + new_db_name: The name of the new database file. + + Returns: + A string containing any errors that occurred. + """ + # Make sure the database name ends with .json + if not new_db_name.endswith('.json'): + new_db_name += '.json' + + path_to_images = Path(path_to_images_folder) + path_to_database = Path(folder_paths.get_folder_paths("EmbDBs")[0]) / new_db_name + + path_to_database.parent.mkdir(exist_ok=True) + + errors = generate_clip_features_json(clip_vision, path_to_images, path_to_database, unique_id) + return errors,