Spaces:
Runtime error
Runtime error
Upload app.py
Browse files
app.py
CHANGED
@@ -69,9 +69,10 @@ def run_sam(predictor, selected_points):
|
|
69 |
)
|
70 |
best_mask = masks[0].astype(np.uint8)
|
71 |
# dilate
|
72 |
-
|
73 |
-
|
74 |
-
|
|
|
75 |
return best_mask
|
76 |
|
77 |
def apply_mask_overlay(image, mask, color=(255, 0, 0)):
|
@@ -105,9 +106,8 @@ def reset_points():
|
|
105 |
|
106 |
@spaces.GPU
|
107 |
def image_to_3d(
|
108 |
-
image:
|
109 |
-
|
110 |
-
is_multiimage: bool,
|
111 |
seed: int,
|
112 |
ss_guidance_strength: float,
|
113 |
ss_sampling_steps: int,
|
@@ -120,37 +120,22 @@ def image_to_3d(
|
|
120 |
ๅฐๅพๅ่ฝฌๆขไธบ 3D ๆจกๅใ
|
121 |
"""
|
122 |
user_dir = os.path.join(TMP_DIR, str(req.session_hash))
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
outputs = pipeline.run_multi_image(
|
140 |
-
[img[0] for img in multiimages],
|
141 |
-
seed=seed,
|
142 |
-
formats=["gaussian", "mesh"],
|
143 |
-
preprocess_image=False,
|
144 |
-
sparse_structure_sampler_params={
|
145 |
-
"steps": ss_sampling_steps,
|
146 |
-
"cfg_strength": ss_guidance_strength,
|
147 |
-
},
|
148 |
-
slat_sampler_params={
|
149 |
-
"steps": slat_sampling_steps,
|
150 |
-
"cfg_strength": slat_guidance_strength,
|
151 |
-
},
|
152 |
-
mode=multiimage_algo,
|
153 |
-
)
|
154 |
video = render_utils.render_video(outputs['gaussian'][0], num_frames=120)['color']
|
155 |
video_geo = render_utils.render_video(outputs['mesh'][0], num_frames=120)['normal']
|
156 |
video = [np.concatenate([video[i], video_geo[i]], axis=1) for i in range(len(video))]
|
@@ -270,48 +255,40 @@ def get_sam_predictor():
|
|
270 |
return sam_predictor
|
271 |
|
272 |
|
273 |
-
def draw_points_on_image(image, point
|
274 |
"""ๅจๅพๅไธ็ปๅถๆๆ็น๏ผpoints ไธบ [(x, y, point_type), ...]"""
|
275 |
image_with_points = image.copy()
|
276 |
x, y = point
|
277 |
-
color = (255, 0, 0)
|
278 |
cv2.circle(image_with_points, (int(x), int(y)), radius=10, color=color, thickness=-1)
|
279 |
return image_with_points
|
280 |
|
281 |
|
282 |
-
def see_point(image, x, y
|
283 |
"""
|
284 |
seeๆไฝ๏ผไธไฟฎๆน points ๅ่กจ๏ผไป
ๅจๅพๅไธไธดๆถๆพ็คบ่ฟไธช็น๏ผ
|
285 |
ๅนถ่ฟๅๆดๆฐๅ็ๅพๅๅๅฝๅๅ่กจ๏ผไธๆดๆฐ๏ผใ
|
286 |
"""
|
287 |
# ๅคๅถๅฝๅๅ่กจ๏ผๅนถๅจๅฏๆฌไธญๅ ไธๆฐ็น๏ผไป
็จไบๆพ็คบ๏ผ
|
288 |
-
updated_image = draw_points_on_image(image, [x,y]
|
289 |
return updated_image
|
290 |
|
291 |
-
def add_point(x, y,
|
292 |
"""
|
293 |
addๆไฝ๏ผๅฐๆฐ็นๆทปๅ ๅฐ points ๅ่กจไธญ๏ผ
|
294 |
ๅนถ่ฟๅๆดๆฐๅ็ๅพๅๅๆฐ็็นๅ่กจใ
|
295 |
"""
|
296 |
-
if
|
297 |
-
|
298 |
-
|
299 |
-
visible_points.append([x, y])
|
300 |
-
else:
|
301 |
-
if [x, y] not in occlusion_points:
|
302 |
-
occlusion_points.append([x, y])
|
303 |
-
return visible_points, occlusion_points
|
304 |
|
305 |
-
def delete_point(
|
306 |
"""
|
307 |
deleteๆไฝ๏ผๅ ้ค points ๅ่กจไธญ็ๆๅไธไธช็น๏ผ
|
308 |
ๅนถ่ฟๅๆดๆฐๅ็ๅพๅๅๆฐ็็นๅ่กจใ
|
309 |
"""
|
310 |
-
|
311 |
-
|
312 |
-
else:
|
313 |
-
occlusion_points.pop()
|
314 |
-
return visible_points, occlusion_points
|
315 |
|
316 |
|
317 |
def clear_all_points(image):
|
@@ -331,23 +308,13 @@ def see_visible_points(image, visible_points):
|
|
331 |
cv2.circle(updated_image, (int(p[0]), int(p[1])), radius=10, color=(255, 0, 0), thickness=-1)
|
332 |
return updated_image
|
333 |
|
334 |
-
def
|
335 |
-
""
|
336 |
-
ๅจๅพๅไธ็ปๅถๆๆ occlusion ็น๏ผ็ปฟ่ฒ๏ผใ
|
337 |
-
"""
|
338 |
-
updated_image = image.copy()
|
339 |
-
for p in occlusion_points:
|
340 |
-
cv2.circle(updated_image, (int(p[0]), int(p[1])), radius=10, color=(0, 255, 0), thickness=-1)
|
341 |
-
return updated_image
|
342 |
-
|
343 |
-
def update_all_points(visible_points, occlusion_points):
|
344 |
-
text = f"Visible Points: {visible_points}\nOcclusion Points: {occlusion_points}"
|
345 |
visible_dropdown_choices = [f"({p[0]}, {p[1]})" for p in visible_points]
|
346 |
-
occlusion_dropdown_choices = [f"({p[0]}, {p[1]})" for p in occlusion_points]
|
347 |
# ่ฟๅๆดๆฐๅญๅ
ธๆฅๆ็กฎ่ฎพ็ฝฎ choices ๅ value
|
348 |
-
return text, gr.Dropdown(label="Select Visible Point to Delete", choices=visible_dropdown_choices, value=None, interactive=True)
|
349 |
|
350 |
-
def delete_selected_visible(image, visible_points,
|
351 |
# selected_value ๆฏ็ฑปไผผ "(x, y)" ็ๅญ็ฌฆไธฒ
|
352 |
try:
|
353 |
selected_index = [f"({p[0]}, {p[1]})" for p in visible_points].index(selected_value)
|
@@ -359,22 +326,8 @@ def delete_selected_visible(image, visible_points, occlusion_points, selected_va
|
|
359 |
# ้ๆฐ็ปๅถๆๆ visible ็น๏ผ็บข่ฒ๏ผ
|
360 |
for p in visible_points:
|
361 |
cv2.circle(updated_image, (int(p[0]), int(p[1])), radius=10, color=(255, 0, 0), thickness=-1)
|
362 |
-
updated_text, vis_dropdown, occ_dropdown = update_all_points(visible_points
|
363 |
-
return updated_image, visible_points,
|
364 |
-
|
365 |
-
def delete_selected_occlusion(image, visible_points, occlusion_points, selected_value):
|
366 |
-
try:
|
367 |
-
selected_index = [f"({p[0]}, {p[1]})" for p in occlusion_points].index(selected_value)
|
368 |
-
except ValueError:
|
369 |
-
selected_index = None
|
370 |
-
if selected_index is not None and 0 <= selected_index < len(occlusion_points):
|
371 |
-
occlusion_points.pop(selected_index)
|
372 |
-
updated_image = image.copy()
|
373 |
-
# ้ๆฐ็ปๅถๆๆ occlusion ็น๏ผ็ปฟ่ฒ๏ผ
|
374 |
-
for p in occlusion_points:
|
375 |
-
cv2.circle(updated_image, (int(p[0]), int(p[1])), radius=10, color=(0, 255, 0), thickness=-1)
|
376 |
-
updated_text, vis_dropdown, occ_dropdown = update_all_points(visible_points, occlusion_points)
|
377 |
-
return updated_image, visible_points, occlusion_points, updated_text, vis_dropdown, occ_dropdown
|
378 |
|
379 |
def add_mask(mask, mask_list):
|
380 |
# check if the mask if same as the last mask in the list
|
@@ -399,43 +352,25 @@ def delete_mask(mask_list):
|
|
399 |
mask_list.pop()
|
400 |
return mask_list
|
401 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
402 |
|
403 |
-
|
404 |
-
"""
|
405 |
-
ๅจๅๅพไธๅ ๅ mask๏ผไฝฟ็จ็บข่ฒ็ปๅถ mask ็่ฝฎๅป๏ผ้ mask ๅบๅๅ ๅ ๆต
็ฐ่ฒๅ้ๆ้ฎ็ฝฉใ
|
406 |
-
"""
|
407 |
-
img_arr = image
|
408 |
-
overlay = img_arr.copy()
|
409 |
-
gray_color = np.array([200, 200, 200], dtype=np.uint8)
|
410 |
-
non_mask = (vis_mask == 0) & (occ_mask == 0)
|
411 |
-
overlay[non_mask] = (0.5 * overlay[non_mask] + 0.5 * gray_color).astype(np.uint8)
|
412 |
-
contours_occ, _ = cv2.findContours(occ_mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
413 |
-
cv2.drawContours(overlay, contours_occ, -1, (0,0,255), 2)
|
414 |
-
contours_vis, _ = cv2.findContours(vis_mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
415 |
-
cv2.drawContours(overlay, contours_vis, -1, (255,0,0), 2)
|
416 |
-
return overlay
|
417 |
|
418 |
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
for mask in occlusion_mask_list:
|
426 |
-
combined_occ_mask = cv2.bitwise_or(combined_mask, mask)
|
427 |
-
# ๆทปๅ visible mask ่พน็ผไฝไธบ occlusion mask ็ไธ้จๅ
|
428 |
-
|
429 |
-
overlay = apply_combined_mask_overlay(image, combined_vis_mask, combined_occ_mask)
|
430 |
-
# 5*5 kernel dilate for occlusion mask
|
431 |
-
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
|
432 |
-
combined_occ_mask = cv2.dilate(combined_occ_mask, kernel, iterations=1)
|
433 |
-
combined_mask[combined_occ_mask > 0] = 128
|
434 |
-
combined_mask[combined_vis_mask > 0] = 255
|
435 |
-
# concat the mask and overlay to be a single image
|
436 |
-
# print(overlay.shape, combined_mask.shape)
|
437 |
-
result = cv2.hconcat([overlay, combined_mask[..., None].repeat(3, axis=-1)])
|
438 |
-
return result
|
439 |
|
440 |
|
441 |
with gr.Blocks(delete_cache=(600, 600)) as demo:
|
@@ -449,9 +384,9 @@ with gr.Blocks(delete_cache=(600, 600)) as demo:
|
|
449 |
occlusion_points_state = gr.State(value=[])
|
450 |
original_image = gr.State(value=None)
|
451 |
visibility_mask = gr.State(value=None)
|
452 |
-
occlusion_mask = gr.State(value=None)
|
453 |
visibility_mask_list = gr.State(value=[])
|
454 |
-
|
|
|
455 |
|
456 |
|
457 |
with gr.Row():
|
@@ -471,25 +406,19 @@ with gr.Blocks(delete_cache=(600, 600)) as demo:
|
|
471 |
with gr.Row():
|
472 |
x_input = gr.Number(label="X Coordinate", value=0)
|
473 |
y_input = gr.Number(label="Y Coordinate", value=0)
|
474 |
-
point_type = gr.Radio(["vis", "occ"], label="Point Prompt Type", value="vis")
|
475 |
with gr.Row():
|
476 |
see_button = gr.Button("Render Point")
|
477 |
add_button = gr.Button("Add Point")
|
478 |
with gr.Row():
|
479 |
-
# ๆฐๅขๆ้ฎ๏ผClearใๅๅซๆฅ็ visible/occlusion
|
480 |
clear_button = gr.Button("Clear Points")
|
481 |
-
see_visible_button = gr.Button("
|
482 |
-
see_occlusion_button = gr.Button("Occluded Points")
|
483 |
with gr.Row():
|
484 |
# ๆฐๅขๆๆฌๆกๅฎๆถๆพ็คบ็นๅ่กจ
|
485 |
points_text = gr.Textbox(label="Points List", interactive=False)
|
486 |
with gr.Row():
|
487 |
# ๆฐๅขไธๆ่ๅ๏ผ็จๆทๅฏ้ๆฉ้่ฆๅ ้ค็็น
|
488 |
visible_points_dropdown = gr.Dropdown(label="Select Visible Point to Delete", choices=[], value=None, interactive=True)
|
489 |
-
occlusion_points_dropdown = gr.Dropdown(label="Select Occlusion Point to Delete", choices=[], value=None, interactive=True)
|
490 |
-
with gr.Row():
|
491 |
delete_visible_button = gr.Button("Delete Selected Visible")
|
492 |
-
delete_occlusion_button = gr.Button("Delete Selected Occlusion")
|
493 |
with gr.Column():
|
494 |
# ็จไบๆพ็คบ SAM ๅๅฒ็ปๆ
|
495 |
visible_mask = gr.Image(label='Visible Mask', interactive=False, height=300)
|
@@ -499,25 +428,31 @@ with gr.Blocks(delete_cache=(600, 600)) as demo:
|
|
499 |
with gr.Row():
|
500 |
render_vis_mask = gr.Button("Render Mask")
|
501 |
undo_vis_mask = gr.Button("Undo Last Mask")
|
502 |
-
|
503 |
with gr.Row():
|
504 |
-
|
505 |
-
add_occ_mask = gr.Button("Add Mask")
|
506 |
-
with gr.Row():
|
507 |
-
render_occ_mask = gr.Button("Render Mask")
|
508 |
-
undo_occ_mask = gr.Button("Undo Last Mask")
|
509 |
-
#
|
510 |
with gr.Row():
|
511 |
gr.Markdown("""* Step 2 - 3D Amodal Completion.
|
512 |
-
* Please first check the obtained mask, and make sure there is no "GAP" between the visible area (white) and occluded area (gray).
|
513 |
* Different random seeds can be tried in "Generation Settings", if you think the results are not ideal.
|
514 |
* If the reconstruction 3D asset is satisfactory, you can extract the GLB file and download it.
|
515 |
""")
|
516 |
with gr.Row():
|
517 |
with gr.Column():
|
518 |
-
|
519 |
-
|
520 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
521 |
|
522 |
# ---------------------------
|
523 |
# ๅๆไบคไบ้ป่พ๏ผ็ฅ๏ผ
|
@@ -529,13 +464,13 @@ with gr.Blocks(delete_cache=(600, 600)) as demo:
|
|
529 |
)
|
530 |
see_button.click(
|
531 |
see_point,
|
532 |
-
inputs=[original_image, x_input, y_input
|
533 |
outputs=[input_image]
|
534 |
)
|
535 |
add_button.click(
|
536 |
add_point,
|
537 |
-
inputs=[x_input, y_input,
|
538 |
-
outputs=[visible_points_state
|
539 |
)
|
540 |
|
541 |
# ---------------------------
|
@@ -551,31 +486,16 @@ with gr.Blocks(delete_cache=(600, 600)) as demo:
|
|
551 |
inputs=[input_image, visible_points_state],
|
552 |
outputs=input_image
|
553 |
)
|
554 |
-
see_occlusion_button.click(
|
555 |
-
see_occlusion_points,
|
556 |
-
inputs=[input_image, occlusion_points_state],
|
557 |
-
outputs=input_image
|
558 |
-
)
|
559 |
# ๅฝ visible_points_state ๆ occlusion_points_state ๅๅๆถ๏ผๆดๆฐๆๆฌๆกๅไธๆ่ๅ
|
560 |
visible_points_state.change(
|
561 |
update_all_points,
|
562 |
-
inputs=[visible_points_state
|
563 |
-
outputs=[points_text, visible_points_dropdown
|
564 |
-
)
|
565 |
-
occlusion_points_state.change(
|
566 |
-
update_all_points,
|
567 |
-
inputs=[visible_points_state, occlusion_points_state],
|
568 |
-
outputs=[points_text, visible_points_dropdown, occlusion_points_dropdown]
|
569 |
)
|
570 |
delete_visible_button.click(
|
571 |
delete_selected_visible,
|
572 |
-
inputs=[input_image, visible_points_state,
|
573 |
-
outputs=[input_image, visible_points_state,
|
574 |
-
)
|
575 |
-
delete_occlusion_button.click(
|
576 |
-
delete_selected_occlusion,
|
577 |
-
inputs=[input_image, visible_points_state, occlusion_points_state, occlusion_points_dropdown],
|
578 |
-
outputs=[input_image, visible_points_state, occlusion_points_state, points_text, visible_points_dropdown, occlusion_points_dropdown]
|
579 |
)
|
580 |
|
581 |
# ็ๆmask็้ป่พ
|
@@ -599,33 +519,20 @@ with gr.Blocks(delete_cache=(600, 600)) as demo:
|
|
599 |
inputs=[visibility_mask_list],
|
600 |
outputs=[visibility_mask_list]
|
601 |
)
|
602 |
-
gen_occ_mask.click(
|
603 |
-
segment_and_overlay,
|
604 |
-
inputs=[original_image, occlusion_points_state, predictor],
|
605 |
-
outputs=[occluded_mask, occlusion_mask]
|
606 |
-
)
|
607 |
-
add_occ_mask.click(
|
608 |
-
add_mask,
|
609 |
-
inputs=[occlusion_mask, occlusion_mask_list],
|
610 |
-
outputs=[occlusion_mask_list]
|
611 |
-
)
|
612 |
-
render_occ_mask.click(
|
613 |
-
vis_mask,
|
614 |
-
inputs=[original_image, occlusion_mask_list],
|
615 |
-
outputs=[occluded_mask]
|
616 |
-
)
|
617 |
-
undo_occ_mask.click(
|
618 |
-
delete_mask,
|
619 |
-
inputs=[occlusion_mask_list],
|
620 |
-
outputs=[occlusion_mask_list]
|
621 |
-
)
|
622 |
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
629 |
|
630 |
|
631 |
# ๅฏๅจ Gradio App
|
|
|
69 |
)
|
70 |
best_mask = masks[0].astype(np.uint8)
|
71 |
# dilate
|
72 |
+
if len(selected_points) > 1:
|
73 |
+
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
|
74 |
+
best_mask = cv2.dilate(best_mask, kernel, iterations=1)
|
75 |
+
best_mask = cv2.erode(best_mask, kernel, iterations=1)
|
76 |
return best_mask
|
77 |
|
78 |
def apply_mask_overlay(image, mask, color=(255, 0, 0)):
|
|
|
106 |
|
107 |
@spaces.GPU
|
108 |
def image_to_3d(
|
109 |
+
image: List[tuple],
|
110 |
+
masks: List[np.ndarray],
|
|
|
111 |
seed: int,
|
112 |
ss_guidance_strength: float,
|
113 |
ss_sampling_steps: int,
|
|
|
120 |
ๅฐๅพๅ่ฝฌๆขไธบ 3D ๆจกๅใ
|
121 |
"""
|
122 |
user_dir = os.path.join(TMP_DIR, str(req.session_hash))
|
123 |
+
outputs = pipeline.run_multi_image(
|
124 |
+
[img[0] for img in image],
|
125 |
+
[mask[0] for mask in masks],
|
126 |
+
seed=seed,
|
127 |
+
formats=["gaussian", "mesh"],
|
128 |
+
preprocess_image=False,
|
129 |
+
sparse_structure_sampler_params={
|
130 |
+
"steps": ss_sampling_steps,
|
131 |
+
"cfg_strength": ss_guidance_strength,
|
132 |
+
},
|
133 |
+
slat_sampler_params={
|
134 |
+
"steps": slat_sampling_steps,
|
135 |
+
"cfg_strength": slat_guidance_strength,
|
136 |
+
},
|
137 |
+
mode=multiimage_algo,
|
138 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
video = render_utils.render_video(outputs['gaussian'][0], num_frames=120)['color']
|
140 |
video_geo = render_utils.render_video(outputs['mesh'][0], num_frames=120)['normal']
|
141 |
video = [np.concatenate([video[i], video_geo[i]], axis=1) for i in range(len(video))]
|
|
|
255 |
return sam_predictor
|
256 |
|
257 |
|
258 |
+
def draw_points_on_image(image, point):
|
259 |
"""ๅจๅพๅไธ็ปๅถๆๆ็น๏ผpoints ไธบ [(x, y, point_type), ...]"""
|
260 |
image_with_points = image.copy()
|
261 |
x, y = point
|
262 |
+
color = (255, 0, 0)
|
263 |
cv2.circle(image_with_points, (int(x), int(y)), radius=10, color=color, thickness=-1)
|
264 |
return image_with_points
|
265 |
|
266 |
|
267 |
+
def see_point(image, x, y):
|
268 |
"""
|
269 |
seeๆไฝ๏ผไธไฟฎๆน points ๅ่กจ๏ผไป
ๅจๅพๅไธไธดๆถๆพ็คบ่ฟไธช็น๏ผ
|
270 |
ๅนถ่ฟๅๆดๆฐๅ็ๅพๅๅๅฝๅๅ่กจ๏ผไธๆดๆฐ๏ผใ
|
271 |
"""
|
272 |
# ๅคๅถๅฝๅๅ่กจ๏ผๅนถๅจๅฏๆฌไธญๅ ไธๆฐ็น๏ผไป
็จไบๆพ็คบ๏ผ
|
273 |
+
updated_image = draw_points_on_image(image, [x,y])
|
274 |
return updated_image
|
275 |
|
276 |
+
def add_point(x, y, visible_points):
|
277 |
"""
|
278 |
addๆไฝ๏ผๅฐๆฐ็นๆทปๅ ๅฐ points ๅ่กจไธญ๏ผ
|
279 |
ๅนถ่ฟๅๆดๆฐๅ็ๅพๅๅๆฐ็็นๅ่กจใ
|
280 |
"""
|
281 |
+
if [x, y] not in visible_points:
|
282 |
+
visible_points.append([x, y])
|
283 |
+
return visible_points
|
|
|
|
|
|
|
|
|
|
|
284 |
|
285 |
+
def delete_point(visible_points):
|
286 |
"""
|
287 |
deleteๆไฝ๏ผๅ ้ค points ๅ่กจไธญ็ๆๅไธไธช็น๏ผ
|
288 |
ๅนถ่ฟๅๆดๆฐๅ็ๅพๅๅๆฐ็็นๅ่กจใ
|
289 |
"""
|
290 |
+
visible_points.pop()
|
291 |
+
return visible_points
|
|
|
|
|
|
|
292 |
|
293 |
|
294 |
def clear_all_points(image):
|
|
|
308 |
cv2.circle(updated_image, (int(p[0]), int(p[1])), radius=10, color=(255, 0, 0), thickness=-1)
|
309 |
return updated_image
|
310 |
|
311 |
+
def update_all_points(visible_points):
|
312 |
+
text = f"Points: {visible_points}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
313 |
visible_dropdown_choices = [f"({p[0]}, {p[1]})" for p in visible_points]
|
|
|
314 |
# ่ฟๅๆดๆฐๅญๅ
ธๆฅๆ็กฎ่ฎพ็ฝฎ choices ๅ value
|
315 |
+
return text, gr.Dropdown(label="Select Visible Point to Delete", choices=visible_dropdown_choices, value=None, interactive=True)
|
316 |
|
317 |
+
def delete_selected_visible(image, visible_points, selected_value):
|
318 |
# selected_value ๆฏ็ฑปไผผ "(x, y)" ็ๅญ็ฌฆไธฒ
|
319 |
try:
|
320 |
selected_index = [f"({p[0]}, {p[1]})" for p in visible_points].index(selected_value)
|
|
|
326 |
# ้ๆฐ็ปๅถๆๆ visible ็น๏ผ็บข่ฒ๏ผ
|
327 |
for p in visible_points:
|
328 |
cv2.circle(updated_image, (int(p[0]), int(p[1])), radius=10, color=(255, 0, 0), thickness=-1)
|
329 |
+
updated_text, vis_dropdown, occ_dropdown = update_all_points(visible_points)
|
330 |
+
return updated_image, visible_points, updated_text, vis_dropdown, occ_dropdown
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
331 |
|
332 |
def add_mask(mask, mask_list):
|
333 |
# check if the mask if same as the last mask in the list
|
|
|
352 |
mask_list.pop()
|
353 |
return mask_list
|
354 |
|
355 |
+
def check_combined_mask(image, mask_list, scale=1.7):
|
356 |
+
updated_image = image.copy()
|
357 |
+
# combine all the mask:
|
358 |
+
combined_mask = np.zeros_like(updated_image[:, :, 0])
|
359 |
+
occluded_mask = np.zeros_like(updated_image[:, :, 0])
|
360 |
+
for mask in mask_list:
|
361 |
+
combined_mask = cv2.bitwise_or(combined_mask, mask)
|
362 |
+
masked_image = updated_image * combined_mask[:, :, None]
|
363 |
+
occluded_mask[combined_mask == 1] = 127
|
364 |
|
365 |
+
return masked_image, occluded_mask
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
366 |
|
367 |
|
368 |
+
|
369 |
+
def get_seed(randomize_seed: bool, seed: int) -> int:
|
370 |
+
"""
|
371 |
+
Get the random seed.
|
372 |
+
"""
|
373 |
+
return np.random.randint(0, MAX_SEED) if randomize_seed else seed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
374 |
|
375 |
|
376 |
with gr.Blocks(delete_cache=(600, 600)) as demo:
|
|
|
384 |
occlusion_points_state = gr.State(value=[])
|
385 |
original_image = gr.State(value=None)
|
386 |
visibility_mask = gr.State(value=None)
|
|
|
387 |
visibility_mask_list = gr.State(value=[])
|
388 |
+
|
389 |
+
combined_mask = gr.State(value=None)
|
390 |
|
391 |
|
392 |
with gr.Row():
|
|
|
406 |
with gr.Row():
|
407 |
x_input = gr.Number(label="X Coordinate", value=0)
|
408 |
y_input = gr.Number(label="Y Coordinate", value=0)
|
|
|
409 |
with gr.Row():
|
410 |
see_button = gr.Button("Render Point")
|
411 |
add_button = gr.Button("Add Point")
|
412 |
with gr.Row():
|
|
|
413 |
clear_button = gr.Button("Clear Points")
|
414 |
+
see_visible_button = gr.Button("Render Added Points")
|
|
|
415 |
with gr.Row():
|
416 |
# ๆฐๅขๆๆฌๆกๅฎๆถๆพ็คบ็นๅ่กจ
|
417 |
points_text = gr.Textbox(label="Points List", interactive=False)
|
418 |
with gr.Row():
|
419 |
# ๆฐๅขไธๆ่ๅ๏ผ็จๆทๅฏ้ๆฉ้่ฆๅ ้ค็็น
|
420 |
visible_points_dropdown = gr.Dropdown(label="Select Visible Point to Delete", choices=[], value=None, interactive=True)
|
|
|
|
|
421 |
delete_visible_button = gr.Button("Delete Selected Visible")
|
|
|
422 |
with gr.Column():
|
423 |
# ็จไบๆพ็คบ SAM ๅๅฒ็ปๆ
|
424 |
visible_mask = gr.Image(label='Visible Mask', interactive=False, height=300)
|
|
|
428 |
with gr.Row():
|
429 |
render_vis_mask = gr.Button("Render Mask")
|
430 |
undo_vis_mask = gr.Button("Undo Last Mask")
|
431 |
+
mask_check = gr.Image(label='Visible Input', interactive=False, height=300)
|
432 |
with gr.Row():
|
433 |
+
check_visible_input = gr.Button("Check Combined Mask, make sure there is no GAP between the visible area (white) and occluded area (gray)")
|
|
|
|
|
|
|
|
|
|
|
434 |
with gr.Row():
|
435 |
gr.Markdown("""* Step 2 - 3D Amodal Completion.
|
|
|
436 |
* Different random seeds can be tried in "Generation Settings", if you think the results are not ideal.
|
437 |
* If the reconstruction 3D asset is satisfactory, you can extract the GLB file and download it.
|
438 |
""")
|
439 |
with gr.Row():
|
440 |
with gr.Column():
|
441 |
+
with gr.Accordion(label="Generation Settings", open=True):
|
442 |
+
seed = gr.Slider(0, MAX_SEED, label="Seed", value=1, step=1)
|
443 |
+
randomize_seed = gr.Checkbox(label="Randomize Seed", value=True)
|
444 |
+
gr.Markdown("Stage 1: Sparse Structure Generation")
|
445 |
+
with gr.Row():
|
446 |
+
ss_guidance_strength = gr.Slider(0.0, 10.0, label="Guidance Strength", value=7.5, step=0.1)
|
447 |
+
ss_sampling_steps = gr.Slider(1, 50, label="Sampling Steps", value=12, step=1)
|
448 |
+
gr.Markdown("Stage 2: Structured Latent Generation")
|
449 |
+
with gr.Row():
|
450 |
+
slat_guidance_strength = gr.Slider(0.0, 10.0, label="Guidance Strength", value=3.0, step=0.1)
|
451 |
+
slat_sampling_steps = gr.Slider(1, 50, label="Sampling Steps", value=12, step=1)
|
452 |
+
generate_btn = gr.Button("Generate")
|
453 |
+
with gr.Column():
|
454 |
+
video_output = gr.Video(label="Generated 3D Asset", autoplay=True, loop=True, height=300)
|
455 |
+
|
456 |
|
457 |
# ---------------------------
|
458 |
# ๅๆไบคไบ้ป่พ๏ผ็ฅ๏ผ
|
|
|
464 |
)
|
465 |
see_button.click(
|
466 |
see_point,
|
467 |
+
inputs=[original_image, x_input, y_input],
|
468 |
outputs=[input_image]
|
469 |
)
|
470 |
add_button.click(
|
471 |
add_point,
|
472 |
+
inputs=[x_input, y_input, visible_points_state],
|
473 |
+
outputs=[visible_points_state]
|
474 |
)
|
475 |
|
476 |
# ---------------------------
|
|
|
486 |
inputs=[input_image, visible_points_state],
|
487 |
outputs=input_image
|
488 |
)
|
|
|
|
|
|
|
|
|
|
|
489 |
# ๅฝ visible_points_state ๆ occlusion_points_state ๅๅๆถ๏ผๆดๆฐๆๆฌๆกๅไธๆ่ๅ
|
490 |
visible_points_state.change(
|
491 |
update_all_points,
|
492 |
+
inputs=[visible_points_state],
|
493 |
+
outputs=[points_text, visible_points_dropdown]
|
|
|
|
|
|
|
|
|
|
|
494 |
)
|
495 |
delete_visible_button.click(
|
496 |
delete_selected_visible,
|
497 |
+
inputs=[input_image, visible_points_state, visible_points_dropdown],
|
498 |
+
outputs=[input_image, visible_points_state, points_text, visible_points_dropdown]
|
|
|
|
|
|
|
|
|
|
|
499 |
)
|
500 |
|
501 |
# ็ๆmask็้ป่พ
|
|
|
519 |
inputs=[visibility_mask_list],
|
520 |
outputs=[visibility_mask_list]
|
521 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
522 |
|
523 |
+
check_visible_input.click(
|
524 |
+
|
525 |
+
|
526 |
+
# 3D Amodal Reconstruction
|
527 |
+
# generate_btn.click(
|
528 |
+
# get_seed,
|
529 |
+
# inputs=[randomize_seed, seed],
|
530 |
+
# outputs=[seed],
|
531 |
+
# ).then(
|
532 |
+
# image_to_3d,
|
533 |
+
# inputs=[original_image, [combined_mask], seed, ss_guidance_strength, ss_sampling_steps, slat_guidance_strength, slat_sampling_steps, "multiimage"],
|
534 |
+
# outputs=[visibility_mask]
|
535 |
+
# )
|
536 |
|
537 |
|
538 |
# ๅฏๅจ Gradio App
|