Update app.py
Browse files
app.py
CHANGED
@@ -4,15 +4,19 @@ from huggingface_hub import hf_hub_download
|
|
4 |
from PIL import Image, ImageDraw
|
5 |
import numpy as np
|
6 |
import json
|
|
|
|
|
7 |
|
|
|
8 |
REPO_ID = "thoucentric/Shelf_Objects_Detection_Yolov7_Pytorch"
|
9 |
FILENAME = "best.pt"
|
10 |
-
|
11 |
yolov7_custom_weights = hf_hub_download(repo_id=REPO_ID, filename=FILENAME)
|
12 |
|
13 |
-
|
|
|
14 |
|
15 |
-
|
|
|
16 |
img_width, img_height = image.size
|
17 |
tiles = []
|
18 |
|
@@ -50,39 +54,76 @@ def draw_bounding_boxes(image, bounding_boxes):
|
|
50 |
draw.text((bbox['xmin'], bbox['ymin']), f"{bbox['class']} {bbox['confidence']:.2f}", fill=color)
|
51 |
return image
|
52 |
|
53 |
-
|
|
|
54 |
if not bounding_boxes:
|
55 |
return []
|
56 |
|
57 |
-
|
58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
|
60 |
-
|
61 |
-
chosen_box = bboxes.pop(0)
|
62 |
-
final_bboxes.append(chosen_box)
|
63 |
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
x2 = min(box1['xmax'], box2['xmax'])
|
68 |
-
y2 = min(box1['ymax'], box2['ymax'])
|
69 |
|
70 |
-
|
71 |
-
|
72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
|
74 |
-
|
75 |
-
|
|
|
76 |
|
77 |
-
|
|
|
|
|
|
|
78 |
|
79 |
-
|
|
|
80 |
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
model.
|
85 |
-
|
|
|
|
|
86 |
all_bounding_boxes = []
|
87 |
|
88 |
for tile, box in tiles:
|
@@ -90,49 +131,126 @@ def object_detection(image, model_choice, conf_threshold=0.25, iou_threshold=0.4
|
|
90 |
adjusted_bboxes = merge_bounding_boxes(results, box)
|
91 |
all_bounding_boxes.extend(adjusted_bboxes)
|
92 |
|
93 |
-
final_bounding_boxes =
|
94 |
image_with_boxes = draw_bounding_boxes(image, final_bounding_boxes)
|
95 |
|
96 |
json_response = json.dumps(final_bounding_boxes, indent=4)
|
97 |
return image_with_boxes, json_response
|
98 |
|
99 |
-
def
|
100 |
-
image.
|
101 |
-
|
102 |
-
|
103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
inputs = [
|
108 |
gr.inputs.Image(shape=(4080, 1836), image_mode="RGB", source="upload", label="Upload Image", optional=False),
|
109 |
-
gr.inputs.Dropdown(["best.pt"], default="best.pt", label="Model"),
|
110 |
gr.inputs.Slider(minimum=0.0, maximum=1.0, default=0.25, step=0.01, label="Confidence Threshold"),
|
111 |
gr.inputs.Slider(minimum=0.0, maximum=1.0, default=0.45, step=0.01, label="IOU Threshold"),
|
112 |
]
|
113 |
outputs_image = gr.outputs.Image(type="pil", label="Output Image")
|
114 |
outputs_json = gr.Textbox(label="Bounding Boxes JSON")
|
115 |
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
examples1 = [["Images/Image1.jpg"]]
|
120 |
-
css = ".output-image {height: 50rem important; width: 100% !important;}, .input-image {height: 50rem !important; width: 100% !important;}"
|
121 |
-
css = ".image-preview {height: auto important;}"
|
122 |
|
|
|
123 |
interface = gr.Interface(
|
124 |
fn=object_detection,
|
125 |
inputs=inputs,
|
126 |
outputs=[outputs_image, outputs_json],
|
127 |
-
title=
|
128 |
-
description=
|
129 |
-
article=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
cache_examples=False,
|
131 |
-
allow_flagging=
|
132 |
-
examples=examples1
|
133 |
)
|
134 |
|
135 |
-
|
|
|
|
|
|
|
|
|
136 |
|
137 |
-
|
138 |
-
|
|
|
4 |
from PIL import Image, ImageDraw
|
5 |
import numpy as np
|
6 |
import json
|
7 |
+
import cv2
|
8 |
+
from scipy.ndimage import gaussian_filter
|
9 |
|
10 |
+
# Constants and Model Downloads
|
11 |
REPO_ID = "thoucentric/Shelf_Objects_Detection_Yolov7_Pytorch"
|
12 |
FILENAME = "best.pt"
|
|
|
13 |
yolov7_custom_weights = hf_hub_download(repo_id=REPO_ID, filename=FILENAME)
|
14 |
|
15 |
+
# Load YOLOv7 Custom Model
|
16 |
+
model = torch.hub.load('Owaiskhan9654/yolov7-1:main', model='custom', path_or_model=yolov7_custom_weights, force_reload=True)
|
17 |
|
18 |
+
# Image Splitting and Merging Functionality
|
19 |
+
def split_image(image, tile_size=640, overlap=160):
|
20 |
img_width, img_height = image.size
|
21 |
tiles = []
|
22 |
|
|
|
54 |
draw.text((bbox['xmin'], bbox['ymin']), f"{bbox['class']} {bbox['confidence']:.2f}", fill=color)
|
55 |
return image
|
56 |
|
57 |
+
# Non-Max Suppression Implementations
|
58 |
+
def soft_nms(bounding_boxes, iou_threshold=0.3, sigma=0.5, score_threshold=0.001):
|
59 |
if not bounding_boxes:
|
60 |
return []
|
61 |
|
62 |
+
def iou(box1, box2):
|
63 |
+
x1 = max(box1['xmin'], box2['xmin'])
|
64 |
+
y1 = max(box1['ymin'], box2['ymin'])
|
65 |
+
x2 = min(box1['xmax'], box2['xmax'])
|
66 |
+
y2 = min(box1['ymax'], box2['ymax'])
|
67 |
+
|
68 |
+
intersection = max(0, x2 - x1) * max(0, y2 - y1)
|
69 |
+
box1_area = (box1['xmax'] - box1['xmin']) * (box1['ymax'] - box1['ymin'])
|
70 |
+
box2_area = (box2['xmax'] - box2['xmin']) * (box2['ymax'] - box2['ymin'])
|
71 |
+
|
72 |
+
union = box1_area + box2_area - intersection
|
73 |
+
return intersection / union
|
74 |
+
|
75 |
+
boxes = sorted(bounding_boxes, key=lambda x: x['confidence'], reverse=True)
|
76 |
+
final_boxes = []
|
77 |
+
|
78 |
+
while boxes:
|
79 |
+
chosen_box = boxes.pop(0)
|
80 |
+
final_boxes.append(chosen_box)
|
81 |
+
|
82 |
+
new_boxes = []
|
83 |
+
for box in boxes:
|
84 |
+
iou_score = iou(chosen_box, box)
|
85 |
+
if iou_score > iou_threshold:
|
86 |
+
box['confidence'] *= np.exp(-(iou_score ** 2) / sigma)
|
87 |
+
if box['confidence'] > score_threshold:
|
88 |
+
new_boxes.append(box)
|
89 |
+
boxes = new_boxes
|
90 |
|
91 |
+
return final_boxes
|
|
|
|
|
92 |
|
93 |
+
# Density Map Generation and Counting Functions
|
94 |
+
def generate_density_map(image, bounding_boxes, sigma=4):
|
95 |
+
density_map = np.zeros((image.height, image.width))
|
|
|
|
|
96 |
|
97 |
+
for bbox in bounding_boxes:
|
98 |
+
center_x = int((bbox['xmin'] + bbox['xmax']) / 2)
|
99 |
+
center_y = int((bbox['ymin'] + bbox['ymax']) / 2)
|
100 |
+
density_map[center_y, center_x] += 1
|
101 |
+
|
102 |
+
density_map = gaussian_filter(density_map, sigma=sigma)
|
103 |
+
return density_map
|
104 |
+
|
105 |
+
def count_from_density_map(density_map, threshold=0.05):
|
106 |
+
return np.sum(density_map > threshold)
|
107 |
|
108 |
+
# Edge Enhancement Functions
|
109 |
+
def apply_edge_enhancement(image):
|
110 |
+
gray_image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2GRAY)
|
111 |
|
112 |
+
sobel_x = cv2.Sobel(gray_image, cv2.CV_64F, 1, 0, ksize=3)
|
113 |
+
sobel_y = cv2.Sobel(gray_image, cv2.CV_64F, 0, 1, ksize=3)
|
114 |
+
sobel_combined = np.sqrt(sobel_x**2 + sobel_y**2)
|
115 |
+
sobel_combined = np.uint8(sobel_combined / sobel_combined.max() * 255)
|
116 |
|
117 |
+
enhanced_image = cv2.cvtColor(sobel_combined, cv2.COLOR_GRAY2RGB)
|
118 |
+
return Image.fromarray(enhanced_image)
|
119 |
|
120 |
+
# Object Detection Functions
|
121 |
+
def object_detection(image, conf_threshold=0.25, iou_threshold=0.45):
|
122 |
+
image = Image.fromarray(image)
|
123 |
+
model.conf = conf_threshold
|
124 |
+
model.iou = iou_threshold
|
125 |
+
|
126 |
+
tiles = split_image(image, tile_size=640, overlap=160)
|
127 |
all_bounding_boxes = []
|
128 |
|
129 |
for tile, box in tiles:
|
|
|
131 |
adjusted_bboxes = merge_bounding_boxes(results, box)
|
132 |
all_bounding_boxes.extend(adjusted_bboxes)
|
133 |
|
134 |
+
final_bounding_boxes = soft_nms(all_bounding_boxes, iou_threshold=iou_threshold)
|
135 |
image_with_boxes = draw_bounding_boxes(image, final_bounding_boxes)
|
136 |
|
137 |
json_response = json.dumps(final_bounding_boxes, indent=4)
|
138 |
return image_with_boxes, json_response
|
139 |
|
140 |
+
def object_detection_with_edge_enhancement(image, conf_threshold=0.25, iou_threshold=0.45):
|
141 |
+
image = Image.fromarray(image)
|
142 |
+
image_enhanced = apply_edge_enhancement(image)
|
143 |
+
|
144 |
+
model.conf = conf_threshold
|
145 |
+
model.iou = iou_threshold
|
146 |
+
|
147 |
+
tiles = split_image(image_enhanced, tile_size=640, overlap=160)
|
148 |
+
all_bounding_boxes = []
|
149 |
+
|
150 |
+
for tile, box in tiles:
|
151 |
+
results = model(tile)
|
152 |
+
adjusted_bboxes = merge_bounding_boxes(results, box)
|
153 |
+
all_bounding_boxes.extend(adjusted_bboxes)
|
154 |
+
|
155 |
+
final_bounding_boxes = soft_nms(all_bounding_boxes, iou_threshold=iou_threshold)
|
156 |
+
image_with_boxes = draw_bounding_boxes(image_enhanced, final_bounding_boxes)
|
157 |
+
|
158 |
+
json_response = json.dumps(final_bounding_boxes, indent=4)
|
159 |
+
return image_with_boxes, json_response
|
160 |
+
|
161 |
+
def object_detection_density_edge(image, conf_threshold=0.25, iou_threshold=0.45):
|
162 |
+
"""Apply edge enhancement and density-based counting."""
|
163 |
+
image = Image.fromarray(image)
|
164 |
+
image_enhanced = apply_edge_enhancement(image)
|
165 |
+
|
166 |
+
model.conf = conf_threshold
|
167 |
+
model.iou = iou_threshold
|
168 |
|
169 |
+
tiles = split_image(image_enhanced, tile_size=640, overlap=160)
|
170 |
+
all_bounding_boxes = []
|
171 |
+
|
172 |
+
for tile, box in tiles:
|
173 |
+
results = model(tile)
|
174 |
+
adjusted_bboxes = merge_bounding_boxes(results, box)
|
175 |
+
all_bounding_boxes.extend(adjusted_bboxes)
|
176 |
|
177 |
+
final_bounding_boxes = soft_nms(all_bounding_boxes, iou_threshold=iou_threshold)
|
178 |
+
density_map = generate_density_map(image_enhanced, final_bounding_boxes)
|
179 |
+
|
180 |
+
density_map_rescaled = cv2.applyColorMap(
|
181 |
+
(density_map / np.max(density_map) * 255).astype(np.uint8),
|
182 |
+
cv2.COLORMAP_JET
|
183 |
+
)
|
184 |
+
density_map_pil = Image.fromarray(cv2.cvtColor(density_map_rescaled, cv2.COLOR_BGR2RGB))
|
185 |
+
image_with_density = Image.blend(image_enhanced, density_map_pil, alpha=0.5)
|
186 |
+
|
187 |
+
json_response = json.dumps(final_bounding_boxes, indent=4)
|
188 |
+
object_count = count_from_density_map(density_map)
|
189 |
+
|
190 |
+
summary = json.dumps({"object_count": int(object_count)}, indent=4)
|
191 |
+
return image_with_density, json_response, summary
|
192 |
+
|
193 |
+
# Gradio Interface Definitions
|
194 |
inputs = [
|
195 |
gr.inputs.Image(shape=(4080, 1836), image_mode="RGB", source="upload", label="Upload Image", optional=False),
|
|
|
196 |
gr.inputs.Slider(minimum=0.0, maximum=1.0, default=0.25, step=0.01, label="Confidence Threshold"),
|
197 |
gr.inputs.Slider(minimum=0.0, maximum=1.0, default=0.45, step=0.01, label="IOU Threshold"),
|
198 |
]
|
199 |
outputs_image = gr.outputs.Image(type="pil", label="Output Image")
|
200 |
outputs_json = gr.Textbox(label="Bounding Boxes JSON")
|
201 |
|
202 |
+
title = "<center>Yolov7 Custom Object Detection</center>"
|
203 |
+
description = "<center>Nolen Felten</center>"
|
204 |
+
footer = ("<br><br><center><b>Item Classes it will detect (Total 140 Classes)</b></center>")
|
|
|
|
|
|
|
205 |
|
206 |
+
# Regular Object Detection Interface
|
207 |
interface = gr.Interface(
|
208 |
fn=object_detection,
|
209 |
inputs=inputs,
|
210 |
outputs=[outputs_image, outputs_json],
|
211 |
+
title=title,
|
212 |
+
description=description,
|
213 |
+
article=footer,
|
214 |
+
cache_examples=False,
|
215 |
+
allow_flagging="never"
|
216 |
+
)
|
217 |
+
|
218 |
+
# Edge Enhanced Object Detection Interface
|
219 |
+
interface_edge = gr.Interface(
|
220 |
+
fn=object_detection_with_edge_enhancement,
|
221 |
+
inputs=inputs,
|
222 |
+
outputs=[outputs_image, outputs_json],
|
223 |
+
title="Object Detection with Edge Enhancement",
|
224 |
+
description=description,
|
225 |
+
article=footer,
|
226 |
+
cache_examples=False,
|
227 |
+
allow_flagging="never"
|
228 |
+
)
|
229 |
+
|
230 |
+
# Edge Enhanced Density-Based Counting Interface
|
231 |
+
inputs_density_edge = [
|
232 |
+
gr.inputs.Image(shape=(4080, 1836), image_mode="RGB", source="upload", label="Upload Image", optional=False),
|
233 |
+
gr.inputs.Slider(minimum=0.0, maximum=1.0, default=0.25, step=0.01, label="Confidence Threshold"),
|
234 |
+
gr.inputs.Slider(minimum=0.0, maximum 1.0, default=0.45, step=0.01, label="IOU Threshold"),
|
235 |
+
]
|
236 |
+
outputs_density_edge = [outputs_image, outputs_json, gr.Textbox(label="Density-based Count Summary")]
|
237 |
+
|
238 |
+
interface_density_edge = gr.Interface(
|
239 |
+
fn=object_detection_density_edge,
|
240 |
+
inputs=inputs_density_edge,
|
241 |
+
outputs=outputs_density_edge,
|
242 |
+
title="Object Detection with Density-Based Counting and Edge Enhancement",
|
243 |
+
description=description,
|
244 |
+
article=footer,
|
245 |
cache_examples=False,
|
246 |
+
allow_flagging="never"
|
|
|
247 |
)
|
248 |
|
249 |
+
# Launch Gradio Interfaces
|
250 |
+
def launch_interfaces():
|
251 |
+
interface.launch(debug=True)
|
252 |
+
interface_edge.launch(debug=True)
|
253 |
+
interface_density_edge.launch(debug=True)
|
254 |
|
255 |
+
if __name__ == "__main__":
|
256 |
+
launch_interfaces()
|