DZRobo commited on
Commit
42c372b
·
1 Parent(s): 5b20491

Improve depth model auto-detection and fallback logic

Browse files

Enhanced depth model path resolution to scan additional directories and prefer local weights, including comfyui_controlnet_aux locations. Updated fallback to use a constant mid-gray tensor for pseudo-depth. Added warnings when no local weights are found and improved robustness of path detection. Fix memory leaking.

README.md CHANGED
@@ -83,7 +83,7 @@ Next:
83
  1. Clone or download this repo into `ComfyUI/custom_nodes/`
84
  2. Install helpers: `pip install -r requirements.txt`
85
  3. I recomend, take my negative LoRA `mg_7lambda_negative.safetensors` in HF https://huggingface.co/DD32/mg_7lambda_negative/blob/main/mg_7lambda_negative.safetensors and place the file in ComfyUI, to `ComfyUI/models/loras`
86
- 4. download model `depth_anything_v2_vitl.pth` https://huggingface.co/depth-anything/Depth-Anything-V2-Large/tree/main and place inside in to `depth-anything/` folder.
87
  5. Workflows
88
  Folder `workflows/` contains ready-to-use graphs:
89
  - `mg_SuperSimple-Workflow.json` — one-node pipeline (2/3/4 steps) with presets
 
83
  1. Clone or download this repo into `ComfyUI/custom_nodes/`
84
  2. Install helpers: `pip install -r requirements.txt`
85
  3. I recomend, take my negative LoRA `mg_7lambda_negative.safetensors` in HF https://huggingface.co/DD32/mg_7lambda_negative/blob/main/mg_7lambda_negative.safetensors and place the file in ComfyUI, to `ComfyUI/models/loras`
86
+ 4. If you have `custom_nodes\comfyui_controlnet_aux\` installed and there is a depth model, then it is usually "picked up" automatically, if not, then, download model `depth_anything_v2_vitl.pth` https://huggingface.co/depth-anything/Depth-Anything-V2-Large/tree/main and place inside in to `depth-anything/` folder.
87
  5. Workflows
88
  Folder `workflows/` contains ready-to-use graphs:
89
  - `mg_SuperSimple-Workflow.json` — one-node pipeline (2/3/4 steps) with presets
mod/easy/mg_controlfusion_easy.py CHANGED
@@ -13,11 +13,31 @@ from ..hard.mg_upscale_module import clear_gpu_and_ram_cache
13
  _DEPTH_INIT = False
14
  _DEPTH_MODEL = None
15
  _DEPTH_PROC = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
 
18
  def _insert_aux_path():
19
  try:
20
- base = os.path.dirname(os.path.dirname(__file__)) # .../custom_nodes
 
 
 
21
  aux_root = os.path.join(base, 'comfyui_controlnet_aux')
22
  aux_src = os.path.join(aux_root, 'src')
23
  for p in (aux_src, aux_root):
@@ -29,9 +49,79 @@ def _insert_aux_path():
29
 
30
  def _try_init_depth_anything(model_path: str):
31
  global _DEPTH_INIT, _DEPTH_MODEL, _DEPTH_PROC
32
- if _DEPTH_INIT:
33
- return _DEPTH_MODEL is not None
34
- _DEPTH_INIT = True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  # Prefer our vendored implementation first
36
  try:
37
  from ...vendor.depth_anything_v2.dpt import DepthAnythingV2 # type: ignore
@@ -133,12 +223,11 @@ def _build_depth_map(image_bhwc: torch.Tensor, res: int, model_path: str, hires_
133
  return d
134
  except Exception:
135
  pass
136
- # Fallback pseudo-depth: luminance + gentle blur
137
- lum = (0.2126 * image_bhwc[..., 0] + 0.7152 * image_bhwc[..., 1] + 0.0722 * image_bhwc[..., 2]).to(dtype=dtype)
138
- x = lum.movedim(-1, 0).unsqueeze(0) if lum.ndim == 3 else lum.unsqueeze(0).unsqueeze(0)
139
- x = F.interpolate(x, size=(H, W), mode='bilinear', align_corners=False)
140
- x = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
141
- return x[0, 0].clamp(0, 1)
142
 
143
 
144
  def _pyracanny(image_bhwc: torch.Tensor,
 
13
  _DEPTH_INIT = False
14
  _DEPTH_MODEL = None
15
  _DEPTH_PROC = None
16
+ _DEPTH_WARNED = False
17
+
18
+
19
+ def _find_custom_nodes_root() -> str | None:
20
+ try:
21
+ here = os.path.abspath(os.path.dirname(__file__))
22
+ cur = here
23
+ for _ in range(6):
24
+ if os.path.basename(cur).lower() == 'custom_nodes':
25
+ return cur
26
+ parent = os.path.dirname(cur)
27
+ if parent == cur:
28
+ break
29
+ cur = parent
30
+ except Exception:
31
+ return None
32
+ return None
33
 
34
 
35
  def _insert_aux_path():
36
  try:
37
+ base = _find_custom_nodes_root()
38
+ if base is None:
39
+ # heuristic fallback: go up four levels from .../mod/easy
40
+ base = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))
41
  aux_root = os.path.join(base, 'comfyui_controlnet_aux')
42
  aux_src = os.path.join(aux_root, 'src')
43
  for p in (aux_src, aux_root):
 
49
 
50
  def _try_init_depth_anything(model_path: str):
51
  global _DEPTH_INIT, _DEPTH_MODEL, _DEPTH_PROC
52
+ # If already loaded, reuse
53
+ if _DEPTH_MODEL is not None:
54
+ return True
55
+ # Resolve model path: allow 'auto' or directory; scan vendor and comfyui_controlnet_aux ckpts tree
56
+ try:
57
+ def _prefer_order(paths):
58
+ order = ["vitl", "vitb", "vits", "vitg"]
59
+ scored = []
60
+ for p in paths:
61
+ name = os.path.basename(p).lower()
62
+ score = 100
63
+ for i, tag in enumerate(order):
64
+ if tag in name:
65
+ score = i
66
+ break
67
+ scored.append((score, p))
68
+ scored.sort(key=lambda x: x[0])
69
+ return [p for _, p in scored]
70
+
71
+ def _resolve_path(mp: str) -> str:
72
+ if isinstance(mp, str) and mp.strip().lower() == "auto":
73
+ mp = ""
74
+ if mp and os.path.isfile(mp):
75
+ return mp
76
+ search_dirs = []
77
+ if mp and os.path.isdir(mp):
78
+ search_dirs.append(mp)
79
+ # vendor depth-anything folder
80
+ base_dir = os.path.join(os.path.dirname(__file__), '..', 'depth-anything')
81
+ search_dirs.append(base_dir)
82
+ # comfyui_controlnet_aux ckpts/depth-anything (and deeper)
83
+ base_custom = _find_custom_nodes_root()
84
+ if base_custom is None:
85
+ base_custom = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))
86
+ aux_ckpts = os.path.join(base_custom, 'comfyui_controlnet_aux', 'ckpts', 'depth-anything')
87
+ search_dirs.append(aux_ckpts)
88
+ cand = []
89
+ for d in search_dirs:
90
+ try:
91
+ if not os.path.isdir(d):
92
+ continue
93
+ for root, _dirs, files in os.walk(d):
94
+ for fn in files:
95
+ fnl = fn.lower()
96
+ key = fnl.replace('-', '_')
97
+ if fnl.endswith('.pth') and ('depth_anything' in key) and ('v2' in key):
98
+ cand.append(os.path.join(root, fn))
99
+ except Exception:
100
+ pass
101
+ if cand:
102
+ return _prefer_order(cand)[0]
103
+ return mp
104
+
105
+ model_path = _resolve_path(model_path)
106
+ except Exception:
107
+ pass
108
+ # If no local weights resolved, bail out to pseudo-depth to avoid heavy auto-download/memory spikes
109
+ try:
110
+ if not (isinstance(model_path, str) and os.path.isfile(model_path)):
111
+ global _DEPTH_WARNED
112
+ if not _DEPTH_WARNED:
113
+ try:
114
+ print("[ControlFusion][Depth/Easy] no local Depth Anything v2 weights found; using pseudo-depth fallback.")
115
+ except Exception:
116
+ pass
117
+ _DEPTH_WARNED = True
118
+ _DEPTH_MODEL = None
119
+ _DEPTH_PROC = False
120
+ return False
121
+ except Exception:
122
+ _DEPTH_MODEL = None
123
+ _DEPTH_PROC = False
124
+ return False
125
  # Prefer our vendored implementation first
126
  try:
127
  from ...vendor.depth_anything_v2.dpt import DepthAnythingV2 # type: ignore
 
223
  return d
224
  except Exception:
225
  pass
226
+ # Fallback depth: constant mid-gray (0.5) for lightweight, uniform guidance
227
+ try:
228
+ return torch.full((H, W), 0.5, device=dev, dtype=dtype)
229
+ except Exception:
230
+ return torch.full((H, W), 0.5, device='cpu', dtype=torch.float32).to(device=dev, dtype=dtype)
 
231
 
232
 
233
  def _pyracanny(image_bhwc: torch.Tensor,
mod/hard/mg_controlfusion.py CHANGED
@@ -12,11 +12,29 @@ from .mg_upscale_module import clear_gpu_and_ram_cache
12
  _DEPTH_INIT = False
13
  _DEPTH_MODEL = None
14
  _DEPTH_PROC = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
 
17
  def _insert_aux_path():
18
  try:
19
- base = os.path.dirname(os.path.dirname(__file__)) # .../custom_nodes
 
 
20
  aux_root = os.path.join(base, 'comfyui_controlnet_aux')
21
  aux_src = os.path.join(aux_root, 'src')
22
  for p in (aux_src, aux_root):
@@ -28,9 +46,9 @@ def _insert_aux_path():
28
 
29
  def _try_init_depth_anything(model_path: str):
30
  global _DEPTH_INIT, _DEPTH_MODEL, _DEPTH_PROC
31
- if _DEPTH_INIT:
32
- return _DEPTH_MODEL is not None
33
- _DEPTH_INIT = True
34
  # Resolve model path: allow 'auto' or directory and prefer vitl>vitb>vits>vitg
35
  try:
36
  def _prefer_order(paths):
@@ -57,12 +75,23 @@ def _try_init_depth_anything(model_path: str):
57
  search_dirs.append(mp)
58
  base_dir = os.path.join(os.path.dirname(__file__), '..', 'depth-anything')
59
  search_dirs.append(base_dir)
 
 
 
 
 
 
60
  cand = []
61
  for d in search_dirs:
62
  try:
63
- for fn in os.listdir(d):
64
- if fn.lower().endswith('.pth') and 'depth_anything_v2' in fn.lower():
65
- cand.append(os.path.join(d, fn))
 
 
 
 
 
66
  except Exception:
67
  pass
68
  if cand:
@@ -72,6 +101,23 @@ def _try_init_depth_anything(model_path: str):
72
  model_path = _resolve_path(model_path)
73
  except Exception:
74
  pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  # Prefer our vendored implementation first
76
  try:
77
  from ...vendor.depth_anything_v2.dpt import DepthAnythingV2 # type: ignore
@@ -189,12 +235,12 @@ def _build_depth_map(image_bhwc: torch.Tensor, res: int, model_path: str, hires_
189
  return d
190
  except Exception:
191
  pass
192
- # Fallback pseudo-depth: luminance + gentle blur
193
- lum = (0.2126 * image_bhwc[..., 0] + 0.7152 * image_bhwc[..., 1] + 0.0722 * image_bhwc[..., 2]).to(dtype=dtype)
194
- x = lum.movedim(-1, 0).unsqueeze(0) if lum.ndim == 3 else lum.unsqueeze(0).unsqueeze(0)
195
- x = F.interpolate(x, size=(H, W), mode='bilinear', align_corners=False)
196
- x = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
197
- return x[0, 0].clamp(0, 1)
198
 
199
 
200
  def _pyracanny(image_bhwc: torch.Tensor,
 
12
  _DEPTH_INIT = False
13
  _DEPTH_MODEL = None
14
  _DEPTH_PROC = None
15
+ _DEPTH_WARNED = False
16
+
17
+ def _find_custom_nodes_root() -> str | None:
18
+ try:
19
+ here = os.path.abspath(os.path.dirname(__file__))
20
+ cur = here
21
+ for _ in range(6):
22
+ if os.path.basename(cur).lower() == 'custom_nodes':
23
+ return cur
24
+ parent = os.path.dirname(cur)
25
+ if parent == cur:
26
+ break
27
+ cur = parent
28
+ except Exception:
29
+ return None
30
+ return None
31
 
32
 
33
  def _insert_aux_path():
34
  try:
35
+ base = _find_custom_nodes_root()
36
+ if base is None:
37
+ base = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))
38
  aux_root = os.path.join(base, 'comfyui_controlnet_aux')
39
  aux_src = os.path.join(aux_root, 'src')
40
  for p in (aux_src, aux_root):
 
46
 
47
  def _try_init_depth_anything(model_path: str):
48
  global _DEPTH_INIT, _DEPTH_MODEL, _DEPTH_PROC
49
+ # If already loaded, reuse
50
+ if _DEPTH_MODEL is not None:
51
+ return True
52
  # Resolve model path: allow 'auto' or directory and prefer vitl>vitb>vits>vitg
53
  try:
54
  def _prefer_order(paths):
 
75
  search_dirs.append(mp)
76
  base_dir = os.path.join(os.path.dirname(__file__), '..', 'depth-anything')
77
  search_dirs.append(base_dir)
78
+ # also scan comfyui_controlnet_aux ckpts/depth-anything recursively if present
79
+ base_custom = _find_custom_nodes_root()
80
+ if base_custom is None:
81
+ base_custom = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))
82
+ aux_ckpts = os.path.join(base_custom, 'comfyui_controlnet_aux', 'ckpts', 'depth-anything')
83
+ search_dirs.append(aux_ckpts)
84
  cand = []
85
  for d in search_dirs:
86
  try:
87
+ if not os.path.isdir(d):
88
+ continue
89
+ for root, _dirs, files in os.walk(d):
90
+ for fn in files:
91
+ fnl = fn.lower()
92
+ key = fnl.replace('-', '_')
93
+ if fnl.endswith('.pth') and ('depth_anything' in key) and ('v2' in key):
94
+ cand.append(os.path.join(root, fn))
95
  except Exception:
96
  pass
97
  if cand:
 
101
  model_path = _resolve_path(model_path)
102
  except Exception:
103
  pass
104
+ # If no local weights resolved, bail out to cheap fallback instead of triggering heavy auto-downloads
105
+ try:
106
+ if not (isinstance(model_path, str) and os.path.isfile(model_path)):
107
+ global _DEPTH_WARNED
108
+ if not _DEPTH_WARNED:
109
+ try:
110
+ print("[ControlFusion][Depth] no local Depth Anything v2 weights found; using pseudo-depth fallback.")
111
+ except Exception:
112
+ pass
113
+ _DEPTH_WARNED = True
114
+ _DEPTH_MODEL = None
115
+ _DEPTH_PROC = False
116
+ return False
117
+ except Exception:
118
+ _DEPTH_MODEL = None
119
+ _DEPTH_PROC = False
120
+ return False
121
  # Prefer our vendored implementation first
122
  try:
123
  from ...vendor.depth_anything_v2.dpt import DepthAnythingV2 # type: ignore
 
235
  return d
236
  except Exception:
237
  pass
238
+ # Fallback depth: constant mid-gray (0.5) to keep uniform guidance without heavy processing
239
+ try:
240
+ return torch.full((H, W), 0.5, device=dev, dtype=dtype)
241
+ except Exception:
242
+ # last-resort tensor creation on CPU
243
+ return torch.full((H, W), 0.5, device='cpu', dtype=torch.float32).to(device=dev, dtype=dtype)
244
 
245
 
246
  def _pyracanny(image_bhwc: torch.Tensor,