nishanth-saka commited on
Commit
1885541
·
verified ·
1 Parent(s): 1214ae6

TILE PATTERN EDIT

Browse files
Files changed (1) hide show
  1. app.py +97 -18
app.py CHANGED
@@ -135,28 +135,107 @@ def _process_saree_core(base_image: Image.Image, pattern_image: Image.Image):
135
  l_clahe = clahe.apply(l_channel)
136
  shading_map = l_clahe / 255.0
137
 
138
- # Tile pattern
139
- pattern_np = np.array(pattern_image.convert("RGB"))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  target_h, target_w = img_np.shape[:2]
141
- pattern_h, pattern_w = pattern_np.shape[:2]
142
- pattern_tiled = np.zeros((target_h, target_w, 3), dtype=np.uint8)
143
- for y in range(0, target_h, pattern_h):
144
- for x in range(0, target_w, pattern_w):
145
- end_y = min(y + pattern_h, target_h)
146
- end_x = min(x + pattern_w, target_w)
147
- pattern_tiled[y:end_y, x:end_x] = pattern_np[0:(end_y - y), 0:(end_x - x)]
148
-
149
- # Blend pattern
150
- normal_map_loaded = normal_map.astype(np.float32)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  shading_map_loaded = np.stack([shading_map] * 3, axis=-1)
 
 
152
 
153
- alpha = 0.7
154
- blended_shading = alpha * shading_map_loaded + (1 - alpha)
155
-
156
- pattern_folded = pattern_tiled.astype(np.float32) / 255.0 * blended_shading
157
- normal_boost = 0.5 + 0.5 * normal_map_loaded[..., 2:3]
158
  pattern_folded *= normal_boost
159
- pattern_folded = np.clip(pattern_folded, 0, 1)
 
 
 
 
 
160
 
161
  # ==========================================================
162
  # Background removal with post-processing (no duplicate blur)
 
135
  l_clahe = clahe.apply(l_channel)
136
  shading_map = l_clahe / 255.0
137
 
138
+ # ==========================================================
139
+ # [PATCHED] TILE PATTERN (soft crossfade) + BLEND
140
+ # Replace the block from "# Tile pattern" through
141
+ # "pattern_folded = np.clip(pattern_folded, 0, 1)"
142
+ # and keep everything below (BG removal etc.) unchanged.
143
+ # ==========================================================
144
+
145
+ # ----- ORIGINAL (hard tiling) — kept for reference -----
146
+ # # Tile pattern
147
+ # pattern_np = np.array(pattern_image.convert("RGB"))
148
+ # target_h, target_w = img_np.shape[:2]
149
+ # pattern_h, pattern_w = pattern_np.shape[:2]
150
+ # pattern_tiled = np.zeros((target_h, target_w, 3), dtype=np.uint8)
151
+ # for y in range(0, target_h, pattern_h):
152
+ # for x in range(0, target_w, pattern_w):
153
+ # end_y = min(y + pattern_h, target_h)
154
+ # end_x = min(x + pattern_w, target_w)
155
+ # pattern_tiled[y:end_y, x:end_x] = pattern_np[0:(end_y - y), 0:(end_x - x)]
156
+ #
157
+ # # Blend pattern
158
+ # normal_map_loaded = normal_map.astype(np.float32)
159
+ # shading_map_loaded = np.stack([shading_map] * 3, axis=-1)
160
+ # alpha = 0.7
161
+ # blended_shading = alpha * shading_map_loaded + (1 - alpha)
162
+ # pattern_folded = pattern_tiled.astype(np.float32) / 255.0 * blended_shading
163
+ # normal_boost = 0.5 + 0.5 * normal_map_loaded[..., 2:3]
164
+ # pattern_folded *= normal_boost
165
+ # pattern_folded = np.clip(pattern_folded, 0, 1)
166
+ # ----- END ORIGINAL -----
167
+
168
+ # ---------- NEW: seam‑free overlapped tiling ----------
169
+ eps = 1e-6
170
+
171
+ # 1) Clean the tile (unpremultiply RGBA to remove black fringe; optional 2px crop)
172
+ _tile_rgba = np.array(pattern_image.convert("RGBA")).astype(np.float32) / 255.0
173
+ _tile_rgb = _tile_rgba[..., :3]
174
+ _tile_a = _tile_rgba[..., 3:4]
175
+ _tile_rgb = np.where(_tile_a > eps, _tile_rgb / np.clip(_tile_a, eps, 1.0), _tile_rgb)
176
+
177
+ _crop = 2 # try 2–3 if fringe persists
178
+ if _tile_rgb.shape[0] > 2*_crop and _tile_rgb.shape[1] > 2*_crop:
179
+ _tile_rgb = _tile_rgb[_crop:-_crop, _crop:-_crop, :]
180
+
181
+ pattern_np = (np.clip(_tile_rgb, 0.0, 1.0) * 255).astype(np.uint8)
182
+
183
+ # 2) Overlapped tiling with cosine crossfade
184
  target_h, target_w = img_np.shape[:2]
185
+ th, tw = pattern_np.shape[:2]
186
+ ov = 6 # overlap width in px (tune 4–12)
187
+
188
+ def _make_weight(h, w, ov_):
189
+ ovh = min(ov_, h // 2)
190
+ ovw = min(ov_, w // 2)
191
+ wy = np.ones((h,), dtype=np.float32)
192
+ wx = np.ones((w,), dtype=np.float32)
193
+ if ovh > 0:
194
+ t = np.linspace(0, np.pi, ovh, endpoint=False)
195
+ ramp = 0.5 - 0.5 * np.cos(t)
196
+ wy[:ovh] = np.minimum(wy[:ovh], ramp)
197
+ wy[-ovh:] = np.minimum(wy[-ovh:], ramp[::-1])
198
+ if ovw > 0:
199
+ t = np.linspace(0, np.pi, ovw, endpoint=False)
200
+ ramp = 0.5 - 0.5 * np.cos(t)
201
+ wx[:ovw] = np.minimum(wx[:ovw], ramp)
202
+ wx[-ovw:] = np.minimum(wx[-ovw:], ramp[::-1])
203
+ return np.outer(wy, wx).astype(np.float32)
204
+
205
+ acc = np.zeros((target_h, target_w, 3), dtype=np.float32)
206
+ wacc = np.zeros((target_h, target_w, 1), dtype=np.float32)
207
+
208
+ stride_y = max(1, th - ov)
209
+ stride_x = max(1, tw - ov)
210
+
211
+ for y in range(0, target_h, stride_y):
212
+ for x in range(0, target_w, stride_x):
213
+ h_crop = min(th, target_h - y)
214
+ w_crop = min(tw, target_w - x)
215
+ tile = pattern_np[:h_crop, :w_crop, :].astype(np.float32) / 255.0
216
+ wmask = _make_weight(h_crop, w_crop, ov)[..., None] # (h,w,1)
217
+
218
+ acc[y:y+h_crop, x:x+w_crop] += tile * wmask
219
+ wacc[y:y+h_crop, x:x+w_crop] += wmask
220
+
221
+ pattern_tiled = acc / np.clip(wacc, eps, None)
222
+ pattern_tiled = np.clip(pattern_tiled, 0.0, 1.0) # float32 in [0,1]
223
+
224
+ # 3) Continue with your shading/normal blending (unchanged)
225
+ normal_map_loaded = normal_map.astype(np.float32)
226
  shading_map_loaded = np.stack([shading_map] * 3, axis=-1)
227
+ alpha = 0.7
228
+ blended_shading = alpha * shading_map_loaded + (1 - alpha)
229
 
230
+ pattern_folded = pattern_tiled * blended_shading
231
+ normal_boost = 0.5 + 0.5 * normal_map_loaded[..., 2:3]
 
 
 
232
  pattern_folded *= normal_boost
233
+ pattern_folded = np.clip(pattern_folded, 0.0, 1.0)
234
+
235
+ # ==========================================================
236
+ # [END PATCHED]
237
+ # ==========================================================
238
+
239
 
240
  # ==========================================================
241
  # Background removal with post-processing (no duplicate blur)