import os import random import sys import torch from typing import Sequence, Mapping, Any, Union import gradio as gr from huggingface_hub import hf_hub_download import spaces from comfy import model_management from nodes import NODE_CLASS_MAPPINGS # Debug: Verify comfy/ directory print("Contents of comfy/ directory:", os.listdir('comfy') if os.path.exists('comfy') else "comfy directory not found") try: from comfy import nodes print("Successfully imported comfy.nodes") except Exception as e: print(f"Failed to import comfy.nodes: {str(e)}") # Ensure /home/user/app/ is searched before /home/user/app/comfy/ sys.path.insert(0, '/home/user/app') print("Modified sys.path:", sys.path) print("Starting Space...") os.makedirs('models/ultralytics/bbox', exist_ok=True) os.makedirs('models/inpaint', exist_ok=True) os.makedirs('models/sams', exist_ok=True) def download_model(repo_id, filename, local_dir): local_path = os.path.join(local_dir, filename) if not os.path.exists(local_path): hf_hub_download(repo_id=repo_id, filename=filename, local_dir=local_dir, force_download=True) else: print(f"Model {filename} already exists. Skipping download.") download_model("Acly/MAT", "MAT_Places512_G_fp16.safetensors", "models/inpaint") download_model("stabilityai/sd-vae-ft-mse-original", "vae-ft-mse-840000-ema-pruned.safetensors", "models/vae") download_model("Ultralytics/YOLOv8", "yolov8m.pt", "models/ultralytics/bbox") download_model("xingren23/comfyflow-models", "sams/sam_vit_b_01ec64.pth", "models/sams") # Comment out JIT file downloads since we're cloning the repository # download_model("camenduru/YoloWorld-EfficientSAM", "efficient_sam_s_cpu.jit", "custom_nodes/ComfyUI-YoloWorld-EfficientSAM") # download_model("camenduru/YoloWorld-EfficientSAM", "efficient_sam_s_gpu.jit", "custom_nodes/ComfyUI-YoloWorld-EfficientSAM") print("Downloaded Models") def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any: if obj is None: raise ValueError("Object is None, cannot retrieve index.") try: return obj[index] except (KeyError, IndexError, TypeError): return obj.get("result", [])[index] if isinstance(obj, dict) and "result" in obj else None def find_path(name: str, path: str = None) -> str: if path is None: path = os.getcwd() if name in os.listdir(path): path_name = os.path.join(path, name) print(f"{name} found: {path_name}") return path_name parent_directory = os.path.dirname(path) if parent_directory == path: return None return find_path(name, parent_directory) def add_comfyui_directory_to_sys_path() -> None: comfyui_path = find_path("ComfyUI") if comfyui_path and os.path.isdir(comfyui_path): sys.path.append(comfyui_path) print(f"'{comfyui_path}' added to sys.path") else: print("⚠️ Warning: 'ComfyUI' directory not found. Ensure it is installed properly.") def add_extra_model_paths() -> None: load_extra_path_config = None try: from main import load_extra_path_config except ImportError: print("Could not import load_extra_path_config from main.py.") try: from app_utils.extra_config import load_extra_path_config except ImportError: print("Could not import load_extra_path_config from utils.extra_config. Skipping extra model paths.") extra_model_paths = find_path("extra_model_paths.yaml") if extra_model_paths is not None and load_extra_path_config is not None: load_extra_path_config(extra_model_paths) else: print("Skipping extra model paths: config file or loader function not found.") add_extra_model_paths() print("Model paths added") import app_utils print("app_utils package imported:", app_utils) print("App_utils directory contents:", os.listdir('app_utils') if os.path.exists('app_utils') else "app_utils not found") print("Parent app_utils directory contents:", os.listdir('../app_utils') if os.path.exists('../app_utils') else "parent app_utils not found") print("------------------") print("Checking for app_utils in sys.modules:", 'app_utils' in sys.modules) if 'app_utils' in sys.modules: print("app_utils module location:", sys.modules['app_utils']) print("Attempting to import app_utils manually...") try: import app_utils print("app_utils imported successfully:", app_utils) print("app_utils.__path__:", getattr(app_utils, '__path__', 'Not a package')) print("app_utils.json_util available:", hasattr(app_utils, 'json_util')) except ImportError as e: print("Failed to import app_utils:", e) print("App_utils directory contents:", os.listdir('app_utils') if os.path.exists('app_utils') else "app_utils not found") print("Parent app_utils directory contents:", os.listdir('../app_utils') if os.path.exists('../app_utils') else "parent app_utils not found") print("Checking for utils in sys.modules:", 'utils' in sys.modules) if 'utils' in sys.modules: print("utils module location:", sys.modules['utils']) print("Attempting to import utils manually...") try: import app_utils print("utils imported successfully:", app_utils) print("utils.__path__:", getattr(app_utils, '__path__', 'Not a package')) print("utils.json_util available:", hasattr(app_utils, 'json_util')) except ImportError as e: print("Failed to import utils:", e) def import_custom_nodes() -> None: import asyncio import execution from nodes import init_extra_nodes import server import importlib.util import traceback # Creating a new event loop and setting it as the default loop loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) NODE_CLASS_MAPPINGS.clear() # Clear previous mappings print("Reloading built-in nodes...") # Creating an instance of PromptServer with the loop server_instance = server.PromptServer(loop) execution.PromptQueue(server_instance) # Load built-in nodes first try: init_extra_nodes() print("Built-in Nodes Loaded:", NODE_CLASS_MAPPINGS.keys()) except Exception as e: print(f"Error loading built-in nodes: {str(e)}") traceback.print_exc() # Debug: List contents of custom_nodes/ print("Custom nodes directory contents:", os.listdir('custom_nodes')) for node_dir in os.listdir('custom_nodes'): node_path = os.path.join('custom_nodes', node_dir) if os.path.isdir(node_path): print(f"Contents of {node_dir}:", os.listdir(node_path)) # Check if __init__.py exists init_path = os.path.join(node_path, '__init__.py') print(f"__init__.py exists in {node_dir}: {os.path.exists(init_path)}") if os.path.exists(init_path): # Attempt to import the module try: module_name = f"custom_nodes.{node_dir}" spec = importlib.util.spec_from_file_location(module_name, init_path) if spec is None: print(f"Failed to create spec for {module_name}") continue module = importlib.util.module_from_spec(spec) sys.modules[module_name] = module spec.loader.exec_module(module) print(f"Successfully imported {module_name}") except Exception as e: print(f"Failed to import {node_dir}: {str(e)}") traceback.print_exc() # Load custom nodes (re-run init_extra_nodes to include custom nodes) print("Reloading custom nodes...") try: init_extra_nodes() except Exception as e: print(f"Error in init_extra_nodes(): {str(e)}") traceback.print_exc() print("All Nodes Loaded:", NODE_CLASS_MAPPINGS.keys()) print("Current working directory:", os.getcwd()) print("Current directory contents:", os.listdir('.')) print("Parent directory contents:", os.listdir('..') if os.path.exists('..') else "No parent directory") print("sys.path:", sys.path) print("Utils directory contents:", os.listdir('utils') if os.path.exists('utils') else "utils not found") print("Parent utils directory contents:", os.listdir('../utils') if os.path.exists('../utils') else "parent utils not found") import_custom_nodes() @spaces.GPU(duration=120) def object_remover(object_name, image): import_custom_nodes() with torch.inference_mode(): loadimage_1 = loadimage.load_image(image=image) yoloworld_esam_zho = NODE_CLASS_MAPPINGS["Yoloworld_ESAM_Zho"]() yoloworld_esam_zho_2 = yoloworld_esam_zho.yoloworld_esam_image( categories=object_name, confidence_threshold=0.10000000000000002, iou_threshold=0.10000000000000002, box_thickness=2, text_thickness=2, text_scale=1, with_confidence=True, with_class_agnostic_nms=False, with_segmentation=True, mask_combined=True, mask_extracted=True, mask_extracted_index=0, yolo_world_model=get_value_at_index(yoloworld_modelloader_zho_3, 0), esam_model=get_value_at_index(esam_modelloader_zho_4, 0), image=get_value_at_index(loadimage_1, 0), ) growmask = NODE_CLASS_MAPPINGS["GrowMask"]() growmask_8 = growmask.expand_mask( expand=30, tapered_corners=True, mask=get_value_at_index(yoloworld_esam_zho_2, 1), ) loadimage = NODE_CLASS_MAPPINGS["LoadImage"]() inpaint_inpaintwithmodel = NODE_CLASS_MAPPINGS["INPAINT_InpaintWithModel"]() inpaint_inpaintwithmodel_12 = inpaint_inpaintwithmodel.inpaint( seed=random.randint(1, 2**64), inpaint_model=get_value_at_index(inpaint_loadinpaintmodel_13, 0), image=get_value_at_index(loadimage_1, 0), mask=get_value_at_index(growmask_8, 0), ) vaeencode = NODE_CLASS_MAPPINGS["VAEEncode"]() vaeencode_18 = vaeencode.encode( pixels=get_value_at_index(inpaint_inpaintwithmodel_12, 0), vae=get_value_at_index(vaeloader_20, 0), ) masktoimage = NODE_CLASS_MAPPINGS["MaskToImage"]() vaedecode = NODE_CLASS_MAPPINGS["VAEDecode"]() image_comparer_rgthree = NODE_CLASS_MAPPINGS["Image Comparer (rgthree)"]() saveimage = NODE_CLASS_MAPPINGS["SaveImage"]() for q in range(1): masktoimage_9 = masktoimage.mask_to_image( mask=get_value_at_index(growmask_8, 0) ) vaedecode_19 = vaedecode.decode( samples=get_value_at_index(vaeencode_18, 0), vae=get_value_at_index(vaeloader_20, 0), ) image_comparer_rgthree_17 = image_comparer_rgthree.compare_images( image_a=get_value_at_index(vaedecode_19, 0), image_b=get_value_at_index(loadimage_1, 0), ) saveimage_24 = saveimage.save_images( filename_prefix="ComfyUI", images=get_value_at_index(inpaint_inpaintwithmodel_12, 0), ) if saveimage_24 and "ui" in saveimage_24 and "images" in saveimage_24["ui"]: output_dir = "output" os.makedirs(output_dir, exist_ok=True) saved_path = os.path.join(output_dir, saveimage_24['ui']['images'][0]['filename']) return saved_path else: raise ValueError("Image generation failed. Check model inputs.") return "Error: Image generation failed." # Check for all required custom nodes required_nodes = [ "Yoloworld_ModelLoader_Zho", "ESAM_ModelLoader_Zho", "Yoloworld_ESAM_Zho", "INPAINT_InpaintWithModel", "INPAINT_LoadInpaintModel", "Image Comparer (rgthree)", "GrowMask", "MaskToImage", "VAEEncode", "VAEDecode", "VAELoader", "LoadImage", "SaveImage" ] missing_nodes = [node for node in required_nodes if node not in NODE_CLASS_MAPPINGS] if missing_nodes: raise KeyError(f"❌ Error: The following required nodes were not found: {missing_nodes}. Check if custom nodes are loaded correctly.") # Load the nodes yoloworld_modelloader_zho = NODE_CLASS_MAPPINGS["Yoloworld_ModelLoader_Zho"]() yoloworld_modelloader_zho_3 = yoloworld_modelloader_zho.load_yolo_world_model( yolo_world_model="yolo_world/m" ) esam_modelloader_zho = NODE_CLASS_MAPPINGS["ESAM_ModelLoader_Zho"]() esam_modelloader_zho_4 = esam_modelloader_zho.load_esam_model(device="CUDA") inpaint_loadinpaintmodel = NODE_CLASS_MAPPINGS["INPAINT_LoadInpaintModel"]() inpaint_loadinpaintmodel_13 = inpaint_loadinpaintmodel.load( model_name="MAT_Places512_G_fp16.safetensors" ) vaeloader = NODE_CLASS_MAPPINGS["VAELoader"]() vaeloader_20 = vaeloader.load_vae( vae_name="vae-ft-mse-840000-ema-pruned.safetensors" ) loadimage = NODE_CLASS_MAPPINGS["LoadImage"]() yoloworld_esam_zho = NODE_CLASS_MAPPINGS["Yoloworld_ESAM_Zho"]() growmask = NODE_CLASS_MAPPINGS["GrowMask"]() inpaint_inpaintwithmodel = NODE_CLASS_MAPPINGS["INPAINT_InpaintWithModel"]() vaeencode = NODE_CLASS_MAPPINGS["VAEEncode"]() masktoimage = NODE_CLASS_MAPPINGS["MaskToImage"]() vaedecode = NODE_CLASS_MAPPINGS["VAEDecode"]() image_comparer_rgthree = NODE_CLASS_MAPPINGS["Image Comparer (rgthree)"]() saveimage = NODE_CLASS_MAPPINGS["SaveImage"]() # Add all the models that load a safetensors file model_loaders = [yoloworld_modelloader_zho_3, esam_modelloader_zho_4, inpaint_loadinpaintmodel_13, vaeloader_20] # Check which models are valid and how to best load them valid_models = [ getattr(loader[0], 'patcher', loader[0]) for loader in model_loaders if not isinstance(loader[0], dict) and not isinstance(getattr(loader[0], 'patcher', None), dict) ] # Finally load the models device = "cuda" if torch.cuda.is_available() else "cpu" model_management.load_models_gpu(valid_models) if device == "cuda" else model_management.load_models_cpu(valid_models) with gr.Blocks() as app: gr.Markdown("# Object Remover") with gr.Column(): image = gr.Image(label="Image", type="filepath") object_name = gr.Textbox(label="Obj_name") generate = gr.Button("Generate") with gr.Column(): output = gr.Image(label="output") generate.click(fn=object_remover, inputs=[image, object_name], outputs=[output]) print("Launching app...") app.launch(share=True, debug=True)