Spaces:
Runtime error
Runtime error
Peng Shiya
commited on
Commit
·
38277a1
1
Parent(s):
cba1a87
feature: separate annotation and cutout
Browse files- .gitignore +2 -1
- app.py +26 -19
- app_configs.py +2 -1
- service.py +23 -1
.gitignore
CHANGED
@@ -1,2 +1,3 @@
|
|
1 |
__pycache__/
|
2 |
-
model/
|
|
|
|
1 |
__pycache__/
|
2 |
+
model/
|
3 |
+
flagged/
|
app.py
CHANGED
@@ -33,31 +33,31 @@ with block:
|
|
33 |
return []
|
34 |
def point_labels_empty():
|
35 |
return []
|
|
|
36 |
point_coords = gr.State(point_coords_empty)
|
37 |
point_labels = gr.State(point_labels_empty)
|
38 |
-
|
|
|
39 |
|
40 |
# UI
|
41 |
-
with gr.
|
42 |
-
with gr.
|
43 |
input_image = gr.Image(label='Input', height=512, type='pil')
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
gr.
|
49 |
-
|
50 |
-
|
51 |
-
cutout_gallery = gr.Gallery()
|
52 |
-
with gr.Tab('Annotation'):
|
53 |
-
masks_annotated_image = gr.AnnotatedImage(label='Segments')
|
54 |
-
|
55 |
# components
|
56 |
-
components = {
|
|
|
|
|
57 |
|
58 |
# event - init coords
|
59 |
def on_reset_btn_click(raw_image):
|
60 |
-
return raw_image, point_coords_empty(), point_labels_empty(), None
|
61 |
reset_btn.click(on_reset_btn_click, [raw_image], [input_image, point_coords, point_labels], queue=False)
|
62 |
|
63 |
def on_input_image_upload(input_image):
|
@@ -91,9 +91,16 @@ with block:
|
|
91 |
point_coords=np.array(inputs[point_coords]),
|
92 |
point_labels=np.array(inputs[point_labels]))
|
93 |
annotated = (image, [(masks[i], f'Mask {i}') for i in range(len(masks))])
|
94 |
-
|
95 |
-
|
96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
|
98 |
if __name__ == '__main__':
|
99 |
block.queue()
|
|
|
33 |
return []
|
34 |
def point_labels_empty():
|
35 |
return []
|
36 |
+
raw_image = gr.Image(type='pil', visible=False)
|
37 |
point_coords = gr.State(point_coords_empty)
|
38 |
point_labels = gr.State(point_labels_empty)
|
39 |
+
masks = gr.State()
|
40 |
+
cutout_idx = gr.State(set())
|
41 |
|
42 |
# UI
|
43 |
+
with gr.Column():
|
44 |
+
with gr.Row():
|
45 |
input_image = gr.Image(label='Input', height=512, type='pil')
|
46 |
+
masks_annotated_image = gr.AnnotatedImage(label='Segments')
|
47 |
+
with gr.Row():
|
48 |
+
point_label_radio = gr.Radio(label='Point Label', choices=[1,0], value=1)
|
49 |
+
reset_btn = gr.Button('Reset')
|
50 |
+
run_btn = gr.Button('Run', variant = 'primary')
|
51 |
+
cutout_galary = gr.Gallery(label='Cutouts', object_fit='contain')
|
52 |
+
|
|
|
|
|
|
|
|
|
53 |
# components
|
54 |
+
components = {
|
55 |
+
point_coords, point_labels, raw_image, masks, cutout_idx,
|
56 |
+
input_image, point_label_radio, reset_btn, run_btn, masks_annotated_image}
|
57 |
|
58 |
# event - init coords
|
59 |
def on_reset_btn_click(raw_image):
|
60 |
+
return raw_image, point_coords_empty(), point_labels_empty(), None, []
|
61 |
reset_btn.click(on_reset_btn_click, [raw_image], [input_image, point_coords, point_labels], queue=False)
|
62 |
|
63 |
def on_input_image_upload(input_image):
|
|
|
91 |
point_coords=np.array(inputs[point_coords]),
|
92 |
point_labels=np.array(inputs[point_labels]))
|
93 |
annotated = (image, [(masks[i], f'Mask {i}') for i in range(len(masks))])
|
94 |
+
return annotated, masks, set()
|
95 |
+
run_btn.click(on_run_btn_click, components, [masks_annotated_image, masks, cutout_idx], queue=True)
|
96 |
+
|
97 |
+
# event - get cutout
|
98 |
+
def on_masks_annotated_image_select(inputs, evt:gr.SelectData):
|
99 |
+
inputs[cutout_idx].add(evt.index)
|
100 |
+
cutouts = [service.cutout(inputs[raw_image], inputs[masks][idx]) for idx in list(inputs[cutout_idx])]
|
101 |
+
tight_cutouts = [service.crop_empty(cutout) for cutout in cutouts]
|
102 |
+
return inputs[cutout_idx], tight_cutouts
|
103 |
+
masks_annotated_image.select(on_masks_annotated_image_select, components, [cutout_idx, cutout_galary])
|
104 |
|
105 |
if __name__ == '__main__':
|
106 |
block.queue()
|
app_configs.py
CHANGED
@@ -2,4 +2,5 @@ model_type = r'vit_b'
|
|
2 |
# model_ckpt_path = None
|
3 |
model_ckpt_path = "checkpoints/sam_vit_b_01ec64.pth"
|
4 |
device = 'cpu'
|
5 |
-
enable_segment_all = False
|
|
|
|
2 |
# model_ckpt_path = None
|
3 |
model_ckpt_path = "checkpoints/sam_vit_b_01ec64.pth"
|
4 |
device = 'cpu'
|
5 |
+
enable_segment_all = False
|
6 |
+
flagging_dir = r'.\flagged'
|
service.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
from typing import IO, List
|
|
|
2 |
import torch
|
3 |
from segment_anything import SamPredictor, sam_model_registry, SamAutomaticMaskGenerator
|
4 |
from PIL import Image
|
@@ -87,4 +88,25 @@ def box_pts_to_xyxy(pt1, pt2):
|
|
87 |
"""
|
88 |
x1, y1 = pt1
|
89 |
x2, y2 = pt2
|
90 |
-
return (min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
from typing import IO, List
|
2 |
+
import cv2
|
3 |
import torch
|
4 |
from segment_anything import SamPredictor, sam_model_registry, SamAutomaticMaskGenerator
|
5 |
from PIL import Image
|
|
|
88 |
"""
|
89 |
x1, y1 = pt1
|
90 |
x2, y2 = pt2
|
91 |
+
return (min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2))
|
92 |
+
|
93 |
+
def crop_empty(image:Image.Image):
|
94 |
+
# Convert image to numpy array
|
95 |
+
np_image = np.array(image)
|
96 |
+
|
97 |
+
# Find non-transparent pixels
|
98 |
+
non_transparent_pixels = np_image[:, :, 3] > 0
|
99 |
+
|
100 |
+
# Calculate bounding box coordinates
|
101 |
+
rows = np.any(non_transparent_pixels, axis=1)
|
102 |
+
cols = np.any(non_transparent_pixels, axis=0)
|
103 |
+
ymin, ymax = np.where(rows)[0][[0, -1]]
|
104 |
+
xmin, xmax = np.where(cols)[0][[0, -1]]
|
105 |
+
|
106 |
+
# Crop the image
|
107 |
+
cropped_image = np_image[ymin:ymax+1, xmin:xmax+1, :]
|
108 |
+
|
109 |
+
# Convert cropped image back to PIL image
|
110 |
+
pil_image = Image.fromarray(cropped_image)
|
111 |
+
|
112 |
+
return pil_image
|