Spaces:
Sleeping
Sleeping
import cv2 | |
import numpy as np | |
from typing import List, Tuple, Dict, Any | |
def detect_cracks_and_holes(frame: np.ndarray) -> Tuple[List[Dict[str, Any]], np.ndarray]: | |
""" | |
Detect cracks and holes in the frame using edge detection and contour analysis. | |
Args: | |
frame: Input frame as a numpy array. | |
Returns: | |
Tuple of (list of detections, annotated frame). | |
""" | |
# Convert to grayscale | |
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) | |
# Apply Gaussian blur to reduce noise | |
blurred = cv2.GaussianBlur(gray, (5, 5), 0) | |
# Edge detection using Canny | |
edges = cv2.Canny(blurred, 50, 150) | |
# Dilate edges to connect nearby edges | |
kernel = np.ones((3, 3), np.uint8) | |
dilated = cv2.dilate(edges, kernel, iterations=1) | |
# Find contours | |
contours, _ = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
detections = [] | |
for i, contour in enumerate(contours): | |
# Calculate the area of the contour | |
area = cv2.contourArea(contour) | |
if area < 100: # Ignore small contours | |
continue | |
# Get bounding box | |
x, y, w, h = cv2.boundingRect(contour) | |
x_min, y_min, x_max, y_max = x, y, x + w, y + h | |
# Determine if it's a crack or hole based on shape and area | |
perimeter = cv2.arcLength(contour, True) | |
circularity = 4 * np.pi * area / (perimeter * perimeter) if perimeter > 0 else 0 | |
# Classify as hole if more circular, crack if elongated | |
dtype = "hole" if circularity > 0.5 else "crack" | |
label = f"{dtype.capitalize()} {i+1}" | |
# Determine severity based on area | |
severity = "Severe" if area > 1000 else "Moderate" if area > 500 else "Mild" | |
detections.append({ | |
"box": [x_min, y_min, x_max, y_max], | |
"label": label, | |
"type": dtype, | |
"severity": severity | |
}) | |
return detections, frame |