fix: resolve ONNX CUDA fallback, Docker e2e infrastructure, and all test failures

- Add safe_onnx_session() to gpu.py with graceful CUDA EP → CPU fallback
- Replace bare ort.InferenceSession() calls across colorize, restore, inpaint, remove_bg
- Add libcublas-12-6 to production Dockerfile for ONNX Runtime CUDA EP
- Add skipIfFeatureNotInstalled guards to remove-bg, blur-faces, smart-crop, ocr, noise-removal e2e specs
- Add AI tool install prompt detection in tools-all.spec.ts
- Add smart-crop to PYTHON_SIDECAR_TOOLS so frontend shows install prompt correctly
- Create Dockerfile.test.dockerignore to include tests/ in test image builds
- Add libheif-examples and exiftool to Dockerfile.test for HEIC and metadata tests
- Regenerate visual regression baselines for Docker/Linux and skip on non-Docker platforms
This commit is contained in:
ashim-hq
2026-04-20 20:53:54 +08:00
parent f67a03bb36
commit 37277e5c09
23 changed files with 203 additions and 94 deletions
+2 -10
View File
@@ -46,19 +46,11 @@ OPENCV_POINTS_PATH = os.environ.get(
def colorize_ddcolor(img_bgr, intensity):
"""Colorize using DDColor ONNX model."""
import onnxruntime as ort
from gpu import safe_onnx_session
emit_progress(15, "Loading DDColor model")
providers = ["CUDAExecutionProvider", "CPUExecutionProvider"]
try:
from gpu import gpu_available
if not gpu_available():
providers = ["CPUExecutionProvider"]
except ImportError:
providers = ["CPUExecutionProvider"]
session = ort.InferenceSession(DDCOLOR_MODEL_PATH, providers=providers)
session = safe_onnx_session(DDCOLOR_MODEL_PATH)
input_name = session.get_inputs()[0].name
input_shape = session.get_inputs()[0].shape
# Dynamic dims are strings ('w', 'h'), so default to 512 if not int
+17
View File
@@ -55,3 +55,20 @@ def onnx_providers():
if gpu_available():
return ["CUDAExecutionProvider", "CPUExecutionProvider"]
return ["CPUExecutionProvider"]
def safe_onnx_session(model_path, providers=None):
"""Create an ONNX Runtime InferenceSession with graceful CUDA EP fallback."""
import onnxruntime as ort
if providers is None:
providers = onnx_providers()
try:
return ort.InferenceSession(model_path, providers=providers)
except Exception as e:
if "CUDAExecutionProvider" in providers:
print(f"[gpu] CUDA EP init failed ({e}), falling back to CPU",
file=sys.stderr, flush=True)
return ort.InferenceSession(model_path, providers=["CPUExecutionProvider"])
raise
+3 -6
View File
@@ -99,7 +99,7 @@ def main():
try:
import cv2
import onnxruntime as ort
import onnxruntime
except ImportError as e:
print(json.dumps({
"success": False,
@@ -110,11 +110,8 @@ def main():
emit_progress(10, "Loading model")
model_path = _get_model_path()
# Configure ONNX Runtime session
from gpu import onnx_providers
providers = onnx_providers()
session = ort.InferenceSession(model_path, providers=providers)
from gpu import safe_onnx_session
session = safe_onnx_session(model_path)
emit_progress(20, "Loading images")
img = Image.open(input_path).convert("RGB")
+10 -1
View File
@@ -76,7 +76,16 @@ def main():
emit_progress(10, "Loading model")
session = new_session(model, providers=onnx_providers())
providers = onnx_providers()
try:
session = new_session(model, providers=providers)
except Exception as e:
if "CUDAExecutionProvider" in providers:
print(f"[remove-bg] GPU session failed ({e}), falling back to CPU",
file=sys.stderr, flush=True)
session = new_session(model, providers=["CPUExecutionProvider"])
else:
raise
emit_progress(25, "Model loaded")
+6 -22
View File
@@ -152,14 +152,10 @@ def inpaint_damage(img_bgr, mask):
Returns:
Restored BGR image with damage inpainted.
"""
import onnxruntime as ort
from gpu import safe_onnx_session
model_path = _get_lama_path()
providers = ["CPUExecutionProvider"]
if "CUDAExecutionProvider" in ort.get_available_providers():
providers.insert(0, "CUDAExecutionProvider")
session = ort.InferenceSession(model_path, providers=providers)
session = safe_onnx_session(model_path)
orig_h, orig_w = img_bgr.shape[:2]
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
@@ -261,7 +257,7 @@ def enhance_faces(img_bgr, fidelity=0.7):
Tuple of (enhanced BGR image, number of faces found).
"""
import mediapipe as mp
import onnxruntime as ort
from gpu import safe_onnx_session
# Detect faces
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
@@ -321,11 +317,7 @@ def enhance_faces(img_bgr, fidelity=0.7):
# Load CodeFormer model
model_path = _get_codeformer_path()
providers = ["CPUExecutionProvider"]
if "CUDAExecutionProvider" in ort.get_available_providers():
providers.insert(0, "CUDAExecutionProvider")
session = ort.InferenceSession(model_path, providers=providers)
session = safe_onnx_session(model_path)
input_names = [inp.name for inp in session.get_inputs()]
result = img_bgr.copy()
@@ -476,20 +468,12 @@ def colorize_bw(img_bgr, intensity=0.85):
Reuses the DDColor model that the colorize tool already downloads.
"""
import onnxruntime as ort
from gpu import safe_onnx_session
if not os.path.exists(DDCOLOR_MODEL_PATH):
return img_bgr, False
providers = ["CPUExecutionProvider"]
try:
from gpu import gpu_available
if gpu_available():
providers.insert(0, "CUDAExecutionProvider")
except ImportError as e:
print(f"[restore] GPU detection unavailable: {e}", file=sys.stderr, flush=True)
session = ort.InferenceSession(DDCOLOR_MODEL_PATH, providers=providers)
session = safe_onnx_session(DDCOLOR_MODEL_PATH)
input_name = session.get_inputs()[0].name
input_shape = session.get_inputs()[0].shape
model_size = (