summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-25 10:18:57 +0200
committerPaul Buetow <paul@buetow.org>2026-03-25 10:18:57 +0200
commitc2477fe84aa96ba1fa6e6e75933d08e84f6921eb (patch)
tree2c88aeb8e6061f5d5d0a46c320c9618d8c18a1c2
parente5934cea4f6cd1ceadd46864886a3f1a7bbe2491 (diff)
photo-enhance: add CodeFormerRestore stub and ximgproc fallback
Two runtime fixes discovered during testing: 1. CodeFormerRestore stub: CodeFormer custom node (comfyui-reactor-node) is not installed on fresh VMs. Added a passthrough stub in smart_photo_node.py that keeps the workflow intact while allowing the other stages to work. Registered last so the real node from a separately installed package takes priority if present. 2. Guided filter fallback: cv2.ximgproc.guidedFilter requires opencv-contrib (opencv-contrib-python-headless). Added a try/except in _apply_detail that falls back to cv2.bilateralFilter when ximgproc is unavailable. The contrib package was also installed on the VM for full quality. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-rw-r--r--smart_photo_node.py62
1 files changed, 56 insertions, 6 deletions
diff --git a/smart_photo_node.py b/smart_photo_node.py
index b7b57ae..f48e5d1 100644
--- a/smart_photo_node.py
+++ b/smart_photo_node.py
@@ -367,15 +367,26 @@ class AdaptivePhotoGrade:
def _apply_detail(self, img: np.ndarray, mult: float, denoise: float) -> np.ndarray:
"""
- Clarity / structure boost via guided-filter edge-preserving decomposition.
- Separates base (low-freq) from detail (high-freq), scales detail by mult,
- optionally denoises the base layer via bilateral filter.
+ Clarity / structure boost via edge-preserving decomposition.
+
+ Uses cv2.ximgproc.guidedFilter when opencv-contrib is available
+ (provides the best edge-preserving base layer separation).
+ Falls back to a bilateral filter base when ximgproc is absent.
+
+ Separates base (low-freq) from detail (high-freq), scales detail by
+ mult, optionally denoises the base layer via bilateral filter.
"""
u8 = (img * 255).astype(np.uint8)
- # Guided filter produces an edge-preserving smooth base layer
- # eps controls smoothing strength (higher = more smoothing)
- base = cv2.ximgproc.guidedFilter(u8, u8, radius=8, eps=int(0.01 * 255 ** 2))
+ # Prefer guided filter (opencv-contrib); fall back to bilateral
+ try:
+ base = cv2.ximgproc.guidedFilter(u8, u8, radius=8, eps=int(0.01 * 255 ** 2))
+ except AttributeError:
+ # opencv-contrib not installed — bilateral filter gives a similar
+ # edge-preserving smooth base at slightly lower quality
+ sigma = max(15, int(denoise * 75))
+ base = cv2.bilateralFilter(u8, d=9, sigmaColor=sigma, sigmaSpace=sigma)
+
detail = u8.astype(np.float32) - base.astype(np.float32)
# Optionally soften the base to reduce noise before adding detail back
@@ -724,6 +735,41 @@ class WritePhotoMetadata:
# ---------------------------------------------------------------------------
+# CodeFormerRestore (stub)
+# ---------------------------------------------------------------------------
+class CodeFormerRestore:
+ """
+ Passthrough stub for CodeFormer face restoration.
+
+ The real implementation requires the comfyui-reactor-node or similar
+ custom node package. This stub passes the image through unchanged so
+ the rest of the pipeline (CLIP, grading, sky, depth) can be tested
+ without CodeFormer installed.
+
+ TODO: replace with the real CodeFormer node once the package is
+ installed (e.g. via ComfyUI Manager or manual install of
+ github.com/Gourieff/comfyui-reactor-node).
+ """
+
+ @classmethod
+ def INPUT_TYPES(cls):
+ return {
+ "required": {
+ "image": ("IMAGE",),
+ "fidelity": ("FLOAT", {"default": 0.7, "min": 0.0, "max": 1.0, "step": 0.05}),
+ }
+ }
+
+ RETURN_TYPES = ("IMAGE",)
+ FUNCTION = "restore"
+ CATEGORY = "image/smart"
+
+ def restore(self, image, fidelity: float = 0.7):
+ print(f"[CodeFormerRestore] STUB — passing image through (fidelity={fidelity} ignored)")
+ return (image,)
+
+
+# ---------------------------------------------------------------------------
# ComfyUI node registration
# ---------------------------------------------------------------------------
NODE_CLASS_MAPPINGS = {
@@ -733,6 +779,9 @@ NODE_CLASS_MAPPINGS = {
"SkyEnhance": SkyEnhance,
"DepthSelectiveSharpen": DepthSelectiveSharpen,
"WritePhotoMetadata": WritePhotoMetadata,
+ # Stub registered last so the real node from another package takes priority
+ # if comfyui-reactor-node or similar is installed alongside this file.
+ "CodeFormerRestore": CodeFormerRestore,
}
NODE_DISPLAY_NAME_MAPPINGS = {
@@ -742,4 +791,5 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"SkyEnhance": "Sky Enhance",
"DepthSelectiveSharpen": "Depth Selective Sharpen",
"WritePhotoMetadata": "Write Photo Metadata",
+ "CodeFormerRestore": "CodeFormer Restore (stub — install reactor-node for real impl)",
}