Spaces:
Sleeping
Sleeping
dragonSwing
commited on
Commit
•
294db91
1
Parent(s):
9c55eca
Fix bool conversion error
Browse files- annotate_anything.py +54 -5
- app.py +12 -7
annotate_anything.py
CHANGED
@@ -1,9 +1,11 @@
|
|
1 |
import argparse
|
|
|
2 |
import json
|
3 |
import os
|
4 |
import sys
|
5 |
import tempfile
|
6 |
|
|
|
7 |
import numpy as np
|
8 |
import supervision as sv
|
9 |
from groundingdino.util.inference import Model as DinoModel
|
@@ -33,6 +35,8 @@ def process(
|
|
33 |
box_threshold,
|
34 |
text_threshold,
|
35 |
iou_threshold,
|
|
|
|
|
36 |
device="cuda",
|
37 |
output_dir=None,
|
38 |
save_ann=True,
|
@@ -49,6 +53,7 @@ def process(
|
|
49 |
image = Image.open(image_path)
|
50 |
image_pil = image.convert("RGB")
|
51 |
image = np.array(image_pil)
|
|
|
52 |
|
53 |
# Extract image metadata
|
54 |
filename = os.path.basename(image_path)
|
@@ -101,27 +106,51 @@ def process(
|
|
101 |
|
102 |
# Segmentation
|
103 |
if task in ["auto", "segment"]:
|
|
|
|
|
|
|
104 |
if detections:
|
105 |
masks, scores = segment(
|
106 |
-
sam_predictor, image=
|
107 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
detections.mask = masks
|
|
|
|
|
|
|
109 |
else:
|
110 |
-
masks = sam_automask_generator.generate(
|
111 |
sorted_generated_masks = sorted(
|
112 |
masks, key=lambda x: x["area"], reverse=True
|
113 |
)
|
114 |
|
115 |
xywh = np.array([mask["bbox"] for mask in sorted_generated_masks])
|
116 |
-
mask = np.array(
|
117 |
-
[mask["segmentation"] for mask in sorted_generated_masks]
|
118 |
-
)
|
119 |
scores = np.array(
|
120 |
[mask["predicted_iou"] for mask in sorted_generated_masks]
|
121 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
detections = sv.Detections(
|
123 |
xyxy=xywh_to_xyxy(boxes_xywh=xywh), mask=mask
|
124 |
)
|
|
|
125 |
|
126 |
# Save annotated image
|
127 |
if output_dir and save_ann:
|
@@ -138,6 +167,13 @@ def process(
|
|
138 |
np.save(mask_enc_path, res)
|
139 |
metadata["assets"]["mask_enc"] = mask_enc_path
|
140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
annotated_image_path = os.path.join(
|
142 |
output_dir, basename + "_annotate.png"
|
143 |
)
|
@@ -372,6 +408,19 @@ if __name__ == "__main__":
|
|
372 |
parser.add_argument(
|
373 |
"--iou-threshold", type=float, default=0.5, help="iou threshold"
|
374 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
375 |
|
376 |
parser.add_argument(
|
377 |
"--no-save-ann",
|
|
|
1 |
import argparse
|
2 |
+
import functools
|
3 |
import json
|
4 |
import os
|
5 |
import sys
|
6 |
import tempfile
|
7 |
|
8 |
+
import cv2
|
9 |
import numpy as np
|
10 |
import supervision as sv
|
11 |
from groundingdino.util.inference import Model as DinoModel
|
|
|
35 |
box_threshold,
|
36 |
text_threshold,
|
37 |
iou_threshold,
|
38 |
+
kernel_size=2,
|
39 |
+
expand_mask=False,
|
40 |
device="cuda",
|
41 |
output_dir=None,
|
42 |
save_ann=True,
|
|
|
53 |
image = Image.open(image_path)
|
54 |
image_pil = image.convert("RGB")
|
55 |
image = np.array(image_pil)
|
56 |
+
orig_image = image.copy()
|
57 |
|
58 |
# Extract image metadata
|
59 |
filename = os.path.basename(image_path)
|
|
|
106 |
|
107 |
# Segmentation
|
108 |
if task in ["auto", "segment"]:
|
109 |
+
kernel = cv2.getStructuringElement(
|
110 |
+
cv2.MORPH_ELLIPSE, (2 * kernel_size + 1, 2 * kernel_size + 1)
|
111 |
+
)
|
112 |
if detections:
|
113 |
masks, scores = segment(
|
114 |
+
sam_predictor, image=orig_image, boxes=detections.xyxy
|
115 |
)
|
116 |
+
if expand_mask:
|
117 |
+
masks = [
|
118 |
+
cv2.dilate(mask.astype(np.uint8), kernel) for mask in masks
|
119 |
+
]
|
120 |
+
else:
|
121 |
+
masks = [
|
122 |
+
cv2.morphologyEx(mask.astype(np.uint8), cv2.MORPH_CLOSE, kernel)
|
123 |
+
for mask in masks
|
124 |
+
]
|
125 |
detections.mask = masks
|
126 |
+
binary_mask = functools.reduce(
|
127 |
+
lambda x, y: x + y, detections.mask
|
128 |
+
).astype(np.bool)
|
129 |
else:
|
130 |
+
masks = sam_automask_generator.generate(orig_image)
|
131 |
sorted_generated_masks = sorted(
|
132 |
masks, key=lambda x: x["area"], reverse=True
|
133 |
)
|
134 |
|
135 |
xywh = np.array([mask["bbox"] for mask in sorted_generated_masks])
|
|
|
|
|
|
|
136 |
scores = np.array(
|
137 |
[mask["predicted_iou"] for mask in sorted_generated_masks]
|
138 |
)
|
139 |
+
if expand_mask:
|
140 |
+
mask = np.array(
|
141 |
+
[
|
142 |
+
cv2.dilate(mask["segmentation"].astype(np.uint8), kernel)
|
143 |
+
for mask in sorted_generated_masks
|
144 |
+
]
|
145 |
+
)
|
146 |
+
else:
|
147 |
+
mask = np.array(
|
148 |
+
[mask["segmentation"] for mask in sorted_generated_masks]
|
149 |
+
)
|
150 |
detections = sv.Detections(
|
151 |
xyxy=xywh_to_xyxy(boxes_xywh=xywh), mask=mask
|
152 |
)
|
153 |
+
binary_mask = None
|
154 |
|
155 |
# Save annotated image
|
156 |
if output_dir and save_ann:
|
|
|
167 |
np.save(mask_enc_path, res)
|
168 |
metadata["assets"]["mask_enc"] = mask_enc_path
|
169 |
|
170 |
+
if binary_mask is not None:
|
171 |
+
cutout_image = np.expand_dims(binary_mask, axis=-1) * orig_image
|
172 |
+
cutout_image_path = os.path.join(
|
173 |
+
output_dir, basename + "_cutout.png"
|
174 |
+
)
|
175 |
+
Image.fromarray(cutout_image).save(cutout_image_path)
|
176 |
+
|
177 |
annotated_image_path = os.path.join(
|
178 |
output_dir, basename + "_annotate.png"
|
179 |
)
|
|
|
408 |
parser.add_argument(
|
409 |
"--iou-threshold", type=float, default=0.5, help="iou threshold"
|
410 |
)
|
411 |
+
parser.add_argument(
|
412 |
+
"--kernel-size",
|
413 |
+
type=int,
|
414 |
+
default=2,
|
415 |
+
choices=range(1, 6),
|
416 |
+
help="kernel size use for smoothing/expanding segment masks",
|
417 |
+
)
|
418 |
+
parser.add_argument(
|
419 |
+
"--expand-mask",
|
420 |
+
action="store_true",
|
421 |
+
default=False,
|
422 |
+
help="If True, expanding segment masks for smoother output.",
|
423 |
+
)
|
424 |
|
425 |
parser.add_argument(
|
426 |
"--no-save-ann",
|
app.py
CHANGED
@@ -175,7 +175,7 @@ def process(
|
|
175 |
detections.mask = masks
|
176 |
binary_mask = functools.reduce(
|
177 |
lambda x, y: x + y, detections.mask
|
178 |
-
).astype(
|
179 |
else:
|
180 |
masks = sam_automask_generator.generate(orig_image)
|
181 |
sorted_generated_masks = sorted(
|
@@ -183,15 +183,20 @@ def process(
|
|
183 |
)
|
184 |
|
185 |
xywh = np.array([mask["bbox"] for mask in sorted_generated_masks])
|
186 |
-
mask = np.array(
|
187 |
-
[
|
188 |
-
cv2.dilate(mask["segmentation"].astype(np.uint8), kernel)
|
189 |
-
for mask in sorted_generated_masks
|
190 |
-
]
|
191 |
-
)
|
192 |
scores = np.array(
|
193 |
[mask["predicted_iou"] for mask in sorted_generated_masks]
|
194 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
detections = sv.Detections(
|
196 |
xyxy=xywh_to_xyxy(boxes_xywh=xywh), mask=mask
|
197 |
)
|
|
|
175 |
detections.mask = masks
|
176 |
binary_mask = functools.reduce(
|
177 |
lambda x, y: x + y, detections.mask
|
178 |
+
).astype(bool)
|
179 |
else:
|
180 |
masks = sam_automask_generator.generate(orig_image)
|
181 |
sorted_generated_masks = sorted(
|
|
|
183 |
)
|
184 |
|
185 |
xywh = np.array([mask["bbox"] for mask in sorted_generated_masks])
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
scores = np.array(
|
187 |
[mask["predicted_iou"] for mask in sorted_generated_masks]
|
188 |
)
|
189 |
+
if expand_mask:
|
190 |
+
mask = np.array(
|
191 |
+
[
|
192 |
+
cv2.dilate(mask["segmentation"].astype(np.uint8), kernel)
|
193 |
+
for mask in sorted_generated_masks
|
194 |
+
]
|
195 |
+
)
|
196 |
+
else:
|
197 |
+
mask = np.array(
|
198 |
+
[mask["segmentation"] for mask in sorted_generated_masks]
|
199 |
+
)
|
200 |
detections = sv.Detections(
|
201 |
xyxy=xywh_to_xyxy(boxes_xywh=xywh), mask=mask
|
202 |
)
|