nishanth-saka commited on
Commit
69e2a87
·
verified ·
1 Parent(s): b165b05
Files changed (1) hide show
  1. app.py +20 -68
app.py CHANGED
@@ -86,73 +86,18 @@ def _process_saree_core(base_image: Image.Image, pattern_image: Image.Image):
86
  l_clahe = clahe.apply(l_channel)
87
  shading_map = l_clahe / 255.0
88
 
89
- # ==========================================================
90
- # Tile pattern (MINIMAL CHANGE: alpha-aware tiling)
91
- # ==========================================================
92
- # pattern_np = np.array(pattern_image.convert("RGB")) # <-- ORIGINAL (kills alpha)
93
- # target_h, target_w = img_np.shape[:2]
94
- # pattern_h, pattern_w = pattern_np.shape[:2]
95
- # pattern_tiled = np.zeros((target_h, target_w, 3), dtype=np.uint8)
96
- # for y in range(0, target_h, pattern_h):
97
- # for x in range(0, target_w, pattern_w):
98
- # end_y = min(y + pattern_h, target_h)
99
- # end_x = min(x + pattern_w, target_w)
100
- # pattern_tiled[y:end_y, x:end_x] = pattern_np[0:(end_y - y), 0:(end_x - x)]
101
-
102
  target_h, target_w = img_np.shape[:2]
 
 
 
 
 
 
 
103
 
104
- # 1) Keep RGBA + light feather on alpha
105
- _rgba = np.array(pattern_image.convert("RGBA"))
106
- _rgb = _rgba[..., :3].astype(np.float32) / 255.0
107
- _a = (_rgba[..., 3].astype(np.float32) / 255.0)
108
- _a = cv2.GaussianBlur(_a, (5, 5), sigmaX=2, sigmaY=2) # small feather
109
- _a = np.clip(_a, 0.0, 1.0)
110
-
111
- # 2) Crop to non-transparent bbox to avoid tiling empty margins
112
- _ys, _xs = np.where(_a > 0.01)
113
- if _ys.size > 0:
114
- y0, y1 = _ys.min(), _ys.max() + 1
115
- x0, x1 = _xs.min(), _xs.max() + 1
116
- _rgb = _rgb[y0:y1, x0:x1, :]
117
- _a = _a[y0:y1, x0:x1]
118
-
119
- ph, pw = _a.shape[:2]
120
-
121
- # 3) Premultiplied source
122
- _rgb_pm = _rgb * _a[..., None]
123
-
124
- # 4) Composite tiles in premultiplied space
125
- _canvas_rgb_pm = np.zeros((target_h, target_w, 3), dtype=np.float32)
126
- _canvas_a = np.zeros((target_h, target_w, 1), dtype=np.float32)
127
-
128
- for y in range(0, target_h, ph):
129
- for x in range(0, target_w, pw):
130
- end_y = min(y + ph, target_h)
131
- end_x = min(x + pw, target_w)
132
- h = end_y - y
133
- w = end_x - x
134
-
135
- src_rgb_pm = _rgb_pm[:h, :w, :]
136
- src_a = _a[:h, :w][..., None]
137
-
138
- dst_rgb_pm = _canvas_rgb_pm[y:end_y, x:end_x, :]
139
- dst_a = _canvas_a[y:end_y, x:end_x, :]
140
-
141
- # Porter-Duff "over" (premultiplied)
142
- out_rgb_pm = src_rgb_pm + dst_rgb_pm * (1.0 - src_a)
143
- out_a = src_a + dst_a * (1.0 - src_a)
144
-
145
- _canvas_rgb_pm[y:end_y, x:end_x, :] = out_rgb_pm
146
- _canvas_a[y:end_y, x:end_x, :] = out_a
147
-
148
- # 5) Un-premultiply to hand back an RGB tile
149
- _alpha_safe = np.clip(_canvas_a, 1e-6, 1.0)
150
- _pattern_rgb = np.clip(_canvas_rgb_pm / _alpha_safe, 0.0, 1.0)
151
- pattern_tiled = (_pattern_rgb * 255).astype(np.uint8)
152
-
153
- # ==========================================================
154
  # Blend pattern
155
- # ==========================================================
156
  normal_map_loaded = normal_map.astype(np.float32)
157
  shading_map_loaded = np.stack([shading_map] * 3, axis=-1)
158
 
@@ -165,22 +110,29 @@ def _process_saree_core(base_image: Image.Image, pattern_image: Image.Image):
165
  pattern_folded = np.clip(pattern_folded, 0, 1)
166
 
167
  # ==========================================================
168
- # Background removal with post-processing
169
  # ==========================================================
170
  buf = BytesIO()
171
  base_image.save(buf, format="PNG")
172
  base_bytes = buf.getvalue()
173
 
 
174
  result_no_bg = bgrem_remove(base_bytes)
175
  mask_img = Image.open(BytesIO(result_no_bg)).convert("RGBA")
176
 
 
177
  mask_alpha = np.array(mask_img)[:, :, 3].astype(np.float32) / 255.0
178
 
179
- kernel = np.ones((5, 5), np.uint8)
180
- mask_binary = (mask_alpha > 0.05).astype(np.uint8) * 255
181
- mask_eroded = cv2.erode(mask_binary, kernel, iterations=3)
 
182
 
 
 
183
  mask_blurred = cv2.GaussianBlur(mask_eroded, (15, 15), sigmaX=3, sigmaY=3)
 
 
184
  mask_blurred = mask_blurred.astype(np.float32) / 255.0
185
 
186
  # Final RGBA
 
86
  l_clahe = clahe.apply(l_channel)
87
  shading_map = l_clahe / 255.0
88
 
89
+ # Tile pattern
90
+ pattern_np = np.array(pattern_image.convert("RGB"))
 
 
 
 
 
 
 
 
 
 
 
91
  target_h, target_w = img_np.shape[:2]
92
+ pattern_h, pattern_w = pattern_np.shape[:2]
93
+ pattern_tiled = np.zeros((target_h, target_w, 3), dtype=np.uint8)
94
+ for y in range(0, target_h, pattern_h):
95
+ for x in range(0, target_w, pattern_w):
96
+ end_y = min(y + pattern_h, target_h)
97
+ end_x = min(x + pattern_w, target_w)
98
+ pattern_tiled[y:end_y, x:end_x] = pattern_np[0:(end_y - y), 0:(end_x - x)]
99
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  # Blend pattern
 
101
  normal_map_loaded = normal_map.astype(np.float32)
102
  shading_map_loaded = np.stack([shading_map] * 3, axis=-1)
103
 
 
110
  pattern_folded = np.clip(pattern_folded, 0, 1)
111
 
112
  # ==========================================================
113
+ # Background removal with post-processing (no duplicate blur)
114
  # ==========================================================
115
  buf = BytesIO()
116
  base_image.save(buf, format="PNG")
117
  base_bytes = buf.getvalue()
118
 
119
+ # Get RGBA from bgrem
120
  result_no_bg = bgrem_remove(base_bytes)
121
  mask_img = Image.open(BytesIO(result_no_bg)).convert("RGBA")
122
 
123
+ # Extract alpha and clean edges
124
  mask_alpha = np.array(mask_img)[:, :, 3].astype(np.float32) / 255.0
125
 
126
+ # 1. Slightly stronger shrink (balanced)
127
+ kernel = np.ones((5, 5), np.uint8) # slightly larger kernel
128
+ mask_binary = (mask_alpha > 0.05).astype(np.uint8) * 255 # slightly stricter threshold
129
+ mask_eroded = cv2.erode(mask_binary, kernel, iterations=3) # balanced erosion
130
 
131
+
132
+ # 2. Feather edges (blur)
133
  mask_blurred = cv2.GaussianBlur(mask_eroded, (15, 15), sigmaX=3, sigmaY=3)
134
+
135
+ # 3. Normalize
136
  mask_blurred = mask_blurred.astype(np.float32) / 255.0
137
 
138
  # Final RGBA