Spaces:
Sleeping
Sleeping
UPDATE: DOMINANT COLOR
Browse files
app.py
CHANGED
|
@@ -49,11 +49,66 @@ def depth_to_normal(depth):
|
|
| 49 |
normal = (normal + 1) / 2
|
| 50 |
return normal
|
| 51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
# ===============================
|
| 53 |
# CORE PROCESSING FUNCTION
|
| 54 |
# ===============================
|
| 55 |
def _process_saree_core(base_image: Image.Image, pattern_image: Image.Image):
|
| 56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
img_np = np.array(img_pil)
|
| 58 |
|
| 59 |
# Prepare tensor
|
|
@@ -129,7 +184,6 @@ def _process_saree_core(base_image: Image.Image, pattern_image: Image.Image):
|
|
| 129 |
mask_binary = (mask_alpha > k/100).astype(np.uint8) * 255 # slightly stricter threshold
|
| 130 |
mask_eroded = cv2.erode(mask_binary, kernel, iterations=3) # balanced erosion
|
| 131 |
|
| 132 |
-
|
| 133 |
# 2. Feather edges (blur)
|
| 134 |
mask_blurred = cv2.GaussianBlur(mask_eroded, (15, 15), sigmaX=3, sigmaY=3)
|
| 135 |
|
|
@@ -268,4 +322,4 @@ async def unhandled_exception_handler(request: Request, exc: Exception):
|
|
| 268 |
|
| 269 |
if __name__ == "__main__":
|
| 270 |
import uvicorn
|
| 271 |
-
uvicorn.run(app, host="0.0.0.0", port=7860)
|
|
|
|
| 49 |
normal = (normal + 1) / 2
|
| 50 |
return normal
|
| 51 |
|
| 52 |
+
# ===============================
|
| 53 |
+
# NEW: Dominant color from non-transparent pixels
|
| 54 |
+
# ===============================
|
| 55 |
+
def dominant_color_from_image(img_rgba: Image.Image, max_samples: int = 10000, k: int = 3):
|
| 56 |
+
"""
|
| 57 |
+
Returns (rgb_tuple, hex_string) for the dominant color considering only alpha>0 pixels.
|
| 58 |
+
Uses K-means on a random subset of pixels for speed.
|
| 59 |
+
"""
|
| 60 |
+
arr = np.array(img_rgba.convert("RGBA"))
|
| 61 |
+
alpha = arr[..., 3]
|
| 62 |
+
mask = alpha > 0
|
| 63 |
+
|
| 64 |
+
if not np.any(mask):
|
| 65 |
+
# Fallback if everything is transparent
|
| 66 |
+
rgb = (255, 255, 255)
|
| 67 |
+
hex_color = "#{:02X}{:02X}{:02X}".format(*rgb)
|
| 68 |
+
return rgb, hex_color
|
| 69 |
+
|
| 70 |
+
rgb_pixels = arr[mask][:, :3].astype(np.float32)
|
| 71 |
+
|
| 72 |
+
# Subsample for speed
|
| 73 |
+
if rgb_pixels.shape[0] > max_samples:
|
| 74 |
+
idx = np.random.choice(rgb_pixels.shape[0], max_samples, replace=False)
|
| 75 |
+
rgb_pixels = rgb_pixels[idx]
|
| 76 |
+
|
| 77 |
+
# K-means
|
| 78 |
+
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0)
|
| 79 |
+
attempts = 3
|
| 80 |
+
compactness, labels, centers = cv2.kmeans(
|
| 81 |
+
data=rgb_pixels,
|
| 82 |
+
K=k,
|
| 83 |
+
bestLabels=None,
|
| 84 |
+
criteria=criteria,
|
| 85 |
+
attempts=attempts,
|
| 86 |
+
flags=cv2.KMEANS_PP_CENTERS
|
| 87 |
+
)
|
| 88 |
+
|
| 89 |
+
# Pick the largest cluster
|
| 90 |
+
counts = np.bincount(labels.flatten(), minlength=k)
|
| 91 |
+
dominant_idx = int(np.argmax(counts))
|
| 92 |
+
dom = centers[dominant_idx].clip(0, 255).astype(np.uint8)
|
| 93 |
+
rgb = (int(dom[0]), int(dom[1]), int(dom[2]))
|
| 94 |
+
hex_color = "#{:02X}{:02X}{:02X}".format(*rgb)
|
| 95 |
+
return rgb, hex_color
|
| 96 |
+
|
| 97 |
# ===============================
|
| 98 |
# CORE PROCESSING FUNCTION
|
| 99 |
# ===============================
|
| 100 |
def _process_saree_core(base_image: Image.Image, pattern_image: Image.Image):
|
| 101 |
+
# ORIGINAL (kept as comment): This converts alpha to black (0,0,0)
|
| 102 |
+
# img_pil = base_image.convert("RGB")
|
| 103 |
+
|
| 104 |
+
# NEW: Matte transparent pixels to the dominant color from the image itself
|
| 105 |
+
base_rgba = base_image.convert("RGBA")
|
| 106 |
+
fill_rgb, fill_hex = dominant_color_from_image(base_rgba)
|
| 107 |
+
bg = Image.new("RGBA", base_rgba.size, fill_rgb + (255,))
|
| 108 |
+
img_pil = Image.alpha_composite(bg, base_rgba).convert("RGB") # <- alpha-aware RGB conversion
|
| 109 |
+
# (Optional) If you want to inspect which color was used:
|
| 110 |
+
# print("Dominant matte color:", fill_hex)
|
| 111 |
+
|
| 112 |
img_np = np.array(img_pil)
|
| 113 |
|
| 114 |
# Prepare tensor
|
|
|
|
| 184 |
mask_binary = (mask_alpha > k/100).astype(np.uint8) * 255 # slightly stricter threshold
|
| 185 |
mask_eroded = cv2.erode(mask_binary, kernel, iterations=3) # balanced erosion
|
| 186 |
|
|
|
|
| 187 |
# 2. Feather edges (blur)
|
| 188 |
mask_blurred = cv2.GaussianBlur(mask_eroded, (15, 15), sigmaX=3, sigmaY=3)
|
| 189 |
|
|
|
|
| 322 |
|
| 323 |
if __name__ == "__main__":
|
| 324 |
import uvicorn
|
| 325 |
+
uvicorn.run(app, host="0.0.0.0", port=7860)
|