Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1360,9 +1360,107 @@ def process_video_file(video_file, analysis_types, processing_mode="Hybrid (Goog
|
|
1360 |
else:
|
1361 |
detection_stats["objects"]["person"] = 1
|
1362 |
else:
|
1363 |
-
# Using YOLO or another DNN-based detector
|
1364 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1365 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1366 |
except Exception as e:
|
1367 |
cv2.putText(frame, f"OpenCV Error: {str(e)}", (10, 110),
|
1368 |
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
|
@@ -2139,6 +2237,49 @@ def main():
|
|
2139 |
# OpenCV parameters
|
2140 |
st.sidebar.markdown("#### OpenCV Parameters")
|
2141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2142 |
track_update_frames = st.sidebar.slider(
|
2143 |
"Update OpenCV tracking every N frames",
|
2144 |
min_value=1,
|
@@ -2255,6 +2396,32 @@ def main():
|
|
2255 |
"blend_results": blend_results
|
2256 |
})
|
2257 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2258 |
# Process the video with the parameters
|
2259 |
processed_video, results = process_video_file(uploaded_file, analysis_types, **processing_params)
|
2260 |
|
|
|
1360 |
else:
|
1361 |
detection_stats["objects"]["person"] = 1
|
1362 |
else:
|
1363 |
+
# Using YOLO or another DNN-based detector
|
1364 |
+
blob = cv2.dnn.blobFromImage(frame, 1/255.0, (416, 416), swapRB=True, crop=False)
|
1365 |
+
opencv_detector.setInput(blob)
|
1366 |
+
|
1367 |
+
# Get output layer names
|
1368 |
+
layer_names = opencv_detector.getLayerNames()
|
1369 |
+
output_layers = []
|
1370 |
+
|
1371 |
+
# Handle different OpenCV versions
|
1372 |
+
try:
|
1373 |
+
if cv2.__version__.startswith('4'):
|
1374 |
+
# OpenCV 4.x
|
1375 |
+
output_layers = [layer_names[i - 1] for i in opencv_detector.getUnconnectedOutLayers()]
|
1376 |
+
else:
|
1377 |
+
# OpenCV 3.x
|
1378 |
+
output_layers = [layer_names[i[0] - 1] for i in opencv_detector.getUnconnectedOutLayers()]
|
1379 |
+
except:
|
1380 |
+
# Fallback method
|
1381 |
+
unconnected_layers = opencv_detector.getUnconnectedOutLayers()
|
1382 |
+
if isinstance(unconnected_layers[0], list) or isinstance(unconnected_layers[0], tuple):
|
1383 |
+
output_layers = [layer_names[i[0] - 1] for i in unconnected_layers]
|
1384 |
+
else:
|
1385 |
+
output_layers = [layer_names[i - 1] for i in unconnected_layers]
|
1386 |
|
1387 |
+
outputs = opencv_detector.forward(output_layers)
|
1388 |
+
|
1389 |
+
# Process detections
|
1390 |
+
class_ids = []
|
1391 |
+
confidences = []
|
1392 |
+
boxes = []
|
1393 |
+
|
1394 |
+
# Define COCO class names
|
1395 |
+
class_names = ["person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat",
|
1396 |
+
"traffic light", "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat",
|
1397 |
+
"dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack",
|
1398 |
+
"umbrella", "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball",
|
1399 |
+
"kite", "baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket",
|
1400 |
+
"bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
|
1401 |
+
"sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair",
|
1402 |
+
"couch", "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse",
|
1403 |
+
"remote", "keyboard", "cell phone", "microwave", "oven", "toaster", "sink", "refrigerator",
|
1404 |
+
"book", "clock", "vase", "scissors", "teddy bear", "hair drier", "toothbrush"]
|
1405 |
+
|
1406 |
+
# Process each detection
|
1407 |
+
for output in outputs:
|
1408 |
+
for detection in output:
|
1409 |
+
scores = detection[5:]
|
1410 |
+
class_id = np.argmax(scores)
|
1411 |
+
confidence = scores[class_id]
|
1412 |
+
|
1413 |
+
if confidence > confidence_threshold:
|
1414 |
+
# Object detected
|
1415 |
+
center_x = int(detection[0] * frame.shape[1])
|
1416 |
+
center_y = int(detection[1] * frame.shape[0])
|
1417 |
+
w = int(detection[2] * frame.shape[1])
|
1418 |
+
h = int(detection[3] * frame.shape[0])
|
1419 |
+
|
1420 |
+
# Rectangle coordinates
|
1421 |
+
x = int(center_x - w / 2)
|
1422 |
+
y = int(center_y - h / 2)
|
1423 |
+
|
1424 |
+
boxes.append([x, y, w, h])
|
1425 |
+
confidences.append(float(confidence))
|
1426 |
+
class_ids.append(class_id)
|
1427 |
+
|
1428 |
+
# Apply non-maximum suppression
|
1429 |
+
indices = cv2.dnn.NMSBoxes(boxes, confidences, confidence_threshold, 0.4)
|
1430 |
+
|
1431 |
+
# Draw the detections
|
1432 |
+
if len(indices) > 0:
|
1433 |
+
for i in indices:
|
1434 |
+
if isinstance(i, (list, tuple)): # Handle different OpenCV versions
|
1435 |
+
i = i[0]
|
1436 |
+
|
1437 |
+
box = boxes[i]
|
1438 |
+
x, y, w, h = box
|
1439 |
+
|
1440 |
+
# Get class name
|
1441 |
+
class_id = class_ids[i]
|
1442 |
+
label = f"{class_names[class_id]}: {int(confidences[i] * 100)}%"
|
1443 |
+
|
1444 |
+
# Different colors for different classes
|
1445 |
+
color = (0, 255, 0) # Default color
|
1446 |
+
|
1447 |
+
# Draw rectangle and label
|
1448 |
+
cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
|
1449 |
+
cv2.putText(frame, label, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
|
1450 |
+
|
1451 |
+
# Add to object trackers for future frames
|
1452 |
+
object_name = class_names[class_id]
|
1453 |
+
object_trackers[f"{object_name}_{i}"] = {
|
1454 |
+
"bbox": (x, y, w, h),
|
1455 |
+
"last_seen": frame_count,
|
1456 |
+
"score": confidences[i]
|
1457 |
+
}
|
1458 |
+
|
1459 |
+
# Update detection stats
|
1460 |
+
if object_name in detection_stats["objects"]:
|
1461 |
+
detection_stats["objects"][object_name] += 1
|
1462 |
+
else:
|
1463 |
+
detection_stats["objects"][object_name] = 1
|
1464 |
except Exception as e:
|
1465 |
cv2.putText(frame, f"OpenCV Error: {str(e)}", (10, 110),
|
1466 |
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
|
|
|
2237 |
# OpenCV parameters
|
2238 |
st.sidebar.markdown("#### OpenCV Parameters")
|
2239 |
|
2240 |
+
# Add YOLO model download option if models aren't found
|
2241 |
+
models_dir = os.path.join(os.path.dirname(__file__), "models")
|
2242 |
+
weights_path = os.path.join(models_dir, "yolov3.weights")
|
2243 |
+
config_path = os.path.join(models_dir, "yolov3.cfg")
|
2244 |
+
|
2245 |
+
if not os.path.exists(models_dir):
|
2246 |
+
os.makedirs(models_dir, exist_ok=True)
|
2247 |
+
|
2248 |
+
if not (os.path.exists(weights_path) and os.path.exists(config_path)):
|
2249 |
+
st.sidebar.warning("⚠️ YOLO models not found. Using basic people detector.")
|
2250 |
+
|
2251 |
+
if st.sidebar.button("Download YOLO Models"):
|
2252 |
+
with st.sidebar.spinner("Downloading YOLO models..."):
|
2253 |
+
# Ensure models directory exists
|
2254 |
+
os.makedirs(models_dir, exist_ok=True)
|
2255 |
+
|
2256 |
+
# Download YOLOv3 config
|
2257 |
+
try:
|
2258 |
+
import urllib.request
|
2259 |
+
|
2260 |
+
# Download config file
|
2261 |
+
if not os.path.exists(config_path):
|
2262 |
+
urllib.request.urlretrieve(
|
2263 |
+
"https://raw.githubusercontent.com/pjreddie/darknet/master/cfg/yolov3.cfg",
|
2264 |
+
config_path
|
2265 |
+
)
|
2266 |
+
st.sidebar.success("Downloaded YOLOv3 config file")
|
2267 |
+
|
2268 |
+
# Download weights file (this is large - about 240MB)
|
2269 |
+
if not os.path.exists(weights_path):
|
2270 |
+
urllib.request.urlretrieve(
|
2271 |
+
"https://pjreddie.com/media/files/yolov3.weights",
|
2272 |
+
weights_path
|
2273 |
+
)
|
2274 |
+
st.sidebar.success("Downloaded YOLOv3 weights file")
|
2275 |
+
|
2276 |
+
st.sidebar.success("YOLO models downloaded successfully! Please refresh the page.")
|
2277 |
+
except Exception as e:
|
2278 |
+
st.sidebar.error(f"Error downloading YOLO models: {str(e)}")
|
2279 |
+
st.sidebar.info("You can manually download the models from: https://pjreddie.com/darknet/yolo/")
|
2280 |
+
else:
|
2281 |
+
st.sidebar.success("✅ YOLO models found. Using advanced object detection.")
|
2282 |
+
|
2283 |
track_update_frames = st.sidebar.slider(
|
2284 |
"Update OpenCV tracking every N frames",
|
2285 |
min_value=1,
|
|
|
2396 |
"blend_results": blend_results
|
2397 |
})
|
2398 |
|
2399 |
+
# Add to the OpenCV parameters section:
|
2400 |
+
with st.sidebar.expander("YOLO Class Filters"):
|
2401 |
+
# Allow users to select which object classes to detect
|
2402 |
+
st.markdown("Select which objects to detect:")
|
2403 |
+
|
2404 |
+
# Create a multiselect with common categories
|
2405 |
+
selected_categories = st.multiselect(
|
2406 |
+
"Object Categories",
|
2407 |
+
["People", "Vehicles", "Animals", "Indoor Objects", "Sports Equipment", "Food", "All"],
|
2408 |
+
default=["People", "Vehicles"]
|
2409 |
+
)
|
2410 |
+
|
2411 |
+
# Map categories to actual YOLO classes
|
2412 |
+
yolo_classes = []
|
2413 |
+
if "People" in selected_categories:
|
2414 |
+
yolo_classes.extend(["person"])
|
2415 |
+
if "Vehicles" in selected_categories:
|
2416 |
+
yolo_classes.extend(["bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck"])
|
2417 |
+
if "Animals" in selected_categories:
|
2418 |
+
yolo_classes.extend(["bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe"])
|
2419 |
+
if "All" in selected_categories:
|
2420 |
+
yolo_classes = None # Detect all classes
|
2421 |
+
|
2422 |
+
# Pass this to your processing function in the processing_params
|
2423 |
+
processing_params["yolo_classes"] = yolo_classes
|
2424 |
+
|
2425 |
# Process the video with the parameters
|
2426 |
processed_video, results = process_video_file(uploaded_file, analysis_types, **processing_params)
|
2427 |
|