lokesh341 commited on
Commit
9e8e688
·
verified ·
1 Parent(s): ecaef7b

Update services/crack_detection_service.py

Browse files
Files changed (1) hide show
  1. services/crack_detection_service.py +115 -0
services/crack_detection_service.py CHANGED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ from PIL import Image
4
+ from ultralytics import YOLO
5
+ from collections import defaultdict
6
+
7
+ # Load YOLOv8 model (yolov8n.pt for lightweight performance)
8
+ try:
9
+ yolo_model = YOLO('yolov8n.pt') # Ultralytics will download the compatible version
10
+ except Exception as e:
11
+ raise RuntimeError(f"Failed to load YOLOv8 model: {str(e)}. Ensure you have an internet connection and the ultralytics package is up to date.")
12
+
13
+ # Simple tracking state to maintain IDs across frames
14
+ class Tracker:
15
+ def __init__(self):
16
+ self.next_id = 0
17
+ self.objects = {} # {id: (centroid, type, box, severity, confidence)}
18
+ self.max_distance = 50 # Max distance to consider same object
19
+
20
+ def update(self, detections):
21
+ new_objects = {}
22
+ for det in detections:
23
+ box = det['box']
24
+ centroid = ((box[0] + box[2]) / 2, (box[1] + box[3]) / 2)
25
+
26
+ best_match_id = None
27
+ min_dist = float('inf')
28
+ for obj_id, (obj_centroid, _, _, _, _) in self.objects.items():
29
+ dist = np.sqrt((centroid[0] - obj_centroid[0])**2 + (centroid[1] - obj_centroid[1])**2)
30
+ if dist < min_dist and dist < self.max_distance:
31
+ min_dist = dist
32
+ best_match_id = obj_id
33
+
34
+ if best_match_id is not None:
35
+ new_objects[best_match_id] = (centroid, det['type'], det['box'], det['severity'], det['confidence'])
36
+ else:
37
+ new_objects[self.next_id] = (centroid, det['type'], det['box'], det['severity'], det['confidence'])
38
+ self.next_id += 1
39
+
40
+ self.objects = new_objects
41
+ return [(obj_id, obj_data[1], obj_data[2], obj_data[3], obj_data[4]) for obj_id, obj_data in self.objects.items()]
42
+
43
+ tracker = Tracker()
44
+
45
+ def segment_road(frame):
46
+ hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
47
+ lower_road = np.array([0, 0, 40])
48
+ upper_road = np.array([180, 40, 160])
49
+ mask = cv2.inRange(hsv, lower_road, upper_road)
50
+ gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
51
+ edges = cv2.Canny(gray, 50, 150)
52
+ edges = cv2.dilate(edges, None, iterations=1)
53
+ mask = cv2.bitwise_and(mask, mask, mask=cv2.bitwise_not(edges))
54
+ kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10, 10))
55
+ mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
56
+ contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
57
+ if contours:
58
+ largest_contour = max(contours, key=cv2.contourArea)
59
+ if cv2.contourArea(largest_contour) > 5000:
60
+ road_mask = np.zeros_like(mask)
61
+ cv2.drawContours(road_mask, [largest_contour], -1, 255, -1)
62
+ return road_mask
63
+ return np.zeros_like(mask)
64
+
65
+ def detect_cracks_and_potholes(frame):
66
+ try:
67
+ road_mask = segment_road(frame)
68
+ masked_frame = cv2.bitwise_and(frame, frame, mask=road_mask)
69
+ gray = cv2.cvtColor(masked_frame, cv2.COLOR_BGR2GRAY)
70
+ blurred = cv2.GaussianBlur(gray, (5, 5), 0)
71
+ edges = cv2.Canny(blurred, 40, 130)
72
+ contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
73
+
74
+ cracks = []
75
+ for contour in contours:
76
+ if cv2.contourArea(contour) < 150:
77
+ continue
78
+ x, y, w, h = cv2.boundingRect(contour)
79
+ area = w * h
80
+ if area > 4000:
81
+ severity = 'Severe'
82
+ elif area > 1200:
83
+ severity = 'Moderate'
84
+ else:
85
+ severity = 'Minor'
86
+ aspect_ratio = float(w) / h if h > 0 else 0
87
+ if 0.3 < aspect_ratio < 7:
88
+ cracks.append({
89
+ 'type': 'crack',
90
+ 'box': [x, y, x + w, y + h],
91
+ 'severity': severity,
92
+ 'confidence': 0.95
93
+ })
94
+
95
+ # Skip YOLO detection since yolov8n.pt can't detect potholes
96
+ potholes = [] # Placeholder; no potholes detected with yolov8n.pt
97
+
98
+ filtered_cracks = cracks
99
+ detections = filtered_cracks + potholes
100
+ tracked_detections = tracker.update(detections)
101
+
102
+ tracked_items = []
103
+ for obj_id, obj_type, box, severity, confidence in tracked_detections:
104
+ tracked_items.append({
105
+ 'id': obj_id,
106
+ 'type': obj_type,
107
+ 'box': box,
108
+ 'severity': severity,
109
+ 'confidence': confidence
110
+ })
111
+
112
+ return tracked_items
113
+ except Exception as e:
114
+ print(f"Error in detection: {str(e)}")
115
+ return []