MrRayZer commited on
Commit
00de18e
·
verified ·
1 Parent(s): c315313

Upload detector.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. detector.py +105 -0
detector.py CHANGED
@@ -143,3 +143,108 @@ class FaceDetector:
143
  indices = np.array(filtered_indices)
144
 
145
  return [boxes[i] for i in keep]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  indices = np.array(filtered_indices)
144
 
145
  return [boxes[i] for i in keep]
146
+
147
+
148
+ class PhoneDetector:
149
+ def __init__(self, model_path="models/yolov8n.onnx"):
150
+ self.model_path = model_path
151
+ self.loaded = False
152
+ self.session = None
153
+
154
+ if os.path.exists(model_path):
155
+ try:
156
+ # Use CPUExecutionProvider for basic server instances
157
+ self.session = ort.InferenceSession(
158
+ model_path,
159
+ providers=['CPUExecutionProvider']
160
+ )
161
+ self.loaded = True
162
+ logger.info(f"YOLOv8 COCO Detector loaded successfully from {model_path}")
163
+ except Exception as e:
164
+ logger.error(f"Error initializing YOLOv8 COCO ONNX session: {e}")
165
+ else:
166
+ logger.warning(f"YOLOv8 COCO model file missing at {model_path}")
167
+
168
+ def detect_phones(self, image_array, confidence_threshold=0.35):
169
+ """
170
+ Detects cell phones in the input image.
171
+ Returns a list of dicts: [{"bbox": [x1, y1, x2, y2], "confidence": score}]
172
+ """
173
+ if not self.loaded or self.session is None:
174
+ return []
175
+
176
+ h, w = image_array.shape[:2]
177
+
178
+ # Preprocess image for YOLOv8 (640x640, float32, normalized, CHW, batch dim)
179
+ input_img = cv2.resize(image_array, (640, 640))
180
+ input_img = input_img.astype(np.float32) / 255.0
181
+ input_img = np.transpose(input_img, (2, 0, 1))
182
+ input_tensor = np.expand_dims(input_img, axis=0)
183
+
184
+ try:
185
+ outputs = self.session.run(
186
+ None,
187
+ {self.session.get_inputs()[0].name: input_tensor}
188
+ )
189
+ # Output is of shape (1, 84, 8400) -> detections are (84, 8400)
190
+ detections = outputs[0][0]
191
+ detections = np.transpose(detections) # Shape: (8400, 84)
192
+ except Exception as e:
193
+ logger.error(f"Error during YOLOv8 COCO inference: {e}")
194
+ return []
195
+
196
+ raw_boxes = []
197
+ raw_scores = []
198
+
199
+ # COCO class 67 is cell phone
200
+ phone_class_idx = 67
201
+ score_idx = 4 + phone_class_idx
202
+
203
+ for pred in detections:
204
+ score = float(pred[score_idx])
205
+ if score > confidence_threshold:
206
+ cx, cy, nw, nh = float(pred[0]), float(pred[1]), float(pred[2]), float(pred[3])
207
+
208
+ # Scale bounding box back to original image size
209
+ x1 = int((cx - nw/2) * (w / 640.0))
210
+ y1 = int((cy - nh/2) * (h / 640.0))
211
+ x2 = int((cx + nw/2) * (w / 640.0))
212
+ y2 = int((cy + nh/2) * (h / 640.0))
213
+
214
+ # Clamp to image boundaries
215
+ x1 = max(0, min(w, x1))
216
+ y1 = max(0, min(h, y1))
217
+ x2 = max(0, min(w, x2))
218
+ y2 = max(0, min(h, y2))
219
+
220
+ # Verify valid box size
221
+ box_w = x2 - x1
222
+ box_h = y2 - y1
223
+ if box_w < 15 or box_h < 15:
224
+ continue
225
+
226
+ raw_boxes.append([x1, y1, x2, y2])
227
+ raw_scores.append(score)
228
+
229
+ if not raw_boxes:
230
+ return []
231
+
232
+ # Apply OpenCV NMS
233
+ keep_indices = cv2.dnn.NMSBoxes(
234
+ bboxes=raw_boxes,
235
+ scores=raw_scores,
236
+ score_threshold=confidence_threshold,
237
+ nms_threshold=0.45
238
+ )
239
+
240
+ filtered_detections = []
241
+ if len(keep_indices) > 0:
242
+ indices = np.array(keep_indices).flatten()
243
+ for idx in indices:
244
+ filtered_detections.append({
245
+ "bbox": raw_boxes[idx],
246
+ "confidence": raw_scores[idx]
247
+ })
248
+
249
+ return filtered_detections
250
+