Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -27,6 +27,40 @@ midas_transforms = torch.hub.load('intel-isl/MiDaS', 'transforms', trust_repo=Tr
|
|
| 27 |
transform = midas_transforms.dpt_transform
|
| 28 |
print("All models loaded!")
|
| 29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
# ================================================
|
| 31 |
# WEATHER DETECTION
|
| 32 |
# ================================================
|
|
@@ -80,11 +114,27 @@ def detect_potholes(input_image):
|
|
| 80 |
img_bgr = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR)
|
| 81 |
H, W = img_rgb.shape[:2]
|
| 82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
weather_label, weather_warning = detect_weather(img_rgb)
|
| 84 |
|
| 85 |
tmp_path = '/tmp/input_image.png'
|
| 86 |
cv2.imwrite(tmp_path, img_bgr)
|
| 87 |
-
|
|
|
|
|
|
|
| 88 |
boxes = results[0].boxes
|
| 89 |
|
| 90 |
inp = transform(img_rgb).to(device)
|
|
@@ -102,7 +152,12 @@ def detect_potholes(input_image):
|
|
| 102 |
if boxes is not None and len(boxes) > 0:
|
| 103 |
for i, box in enumerate(boxes.xyxy):
|
| 104 |
x1, y1, x2, y2 = map(int, box.tolist())
|
| 105 |
-
conf
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
bw, bh = x2-x1, y2-y1
|
| 107 |
area_ratio = (bw * bh) / (H * W)
|
| 108 |
bw_cm = px_to_cm(bw, W)
|
|
@@ -114,7 +169,7 @@ def detect_potholes(input_image):
|
|
| 114 |
severity_counts[sev] += 1
|
| 115 |
cnorm = tuple(c/255 for c in crgb)
|
| 116 |
pothole_data.append(dict(
|
| 117 |
-
id=
|
| 118 |
confidence=conf, width_cm=bw_cm, height_cm=bh_cm,
|
| 119 |
area_cm2=bw_cm*bh_cm, area_pct=area_ratio*100,
|
| 120 |
depth_cm=depth_cm, risk=risk, color=cnorm,
|
|
|
|
| 27 |
transform = midas_transforms.dpt_transform
|
| 28 |
print("All models loaded!")
|
| 29 |
|
| 30 |
+
# ================================================
|
| 31 |
+
# ROAD IMAGE CHECK
|
| 32 |
+
# ================================================
|
| 33 |
+
def is_road_image(img_rgb):
|
| 34 |
+
"""
|
| 35 |
+
Returns True only if the image looks like a road/ground surface.
|
| 36 |
+
Checks for dark/grey ground tones typical of asphalt.
|
| 37 |
+
"""
|
| 38 |
+
gray = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2GRAY)
|
| 39 |
+
h, w = gray.shape
|
| 40 |
+
|
| 41 |
+
# Check bottom half of image (road is usually at the bottom)
|
| 42 |
+
bottom = img_rgb[h//2:, :, :]
|
| 43 |
+
r = bottom[:,:,0].astype(float)
|
| 44 |
+
g = bottom[:,:,1].astype(float)
|
| 45 |
+
b = bottom[:,:,2].astype(float)
|
| 46 |
+
|
| 47 |
+
# Asphalt/road pixels are dark grey: low brightness, low saturation
|
| 48 |
+
brightness = np.mean(gray)
|
| 49 |
+
mean_r = np.mean(r)
|
| 50 |
+
mean_g = np.mean(g)
|
| 51 |
+
mean_b = np.mean(b)
|
| 52 |
+
|
| 53 |
+
# Channel difference — road pixels have similar R,G,B (grey)
|
| 54 |
+
channel_diff = np.mean(np.abs(r - g) + np.abs(g - b) + np.abs(r - b))
|
| 55 |
+
|
| 56 |
+
# Road: moderate brightness, low channel variance, greyish
|
| 57 |
+
is_grey_enough = channel_diff < 60 # road is grey (not colorful)
|
| 58 |
+
is_dark_enough = brightness < 180 # road is not very bright
|
| 59 |
+
is_not_sky = mean_b < 160 # sky images have high blue
|
| 60 |
+
is_not_logo = brightness > 20 # logos/black images excluded
|
| 61 |
+
|
| 62 |
+
return is_grey_enough and is_dark_enough and is_not_sky and is_not_logo
|
| 63 |
+
|
| 64 |
# ================================================
|
| 65 |
# WEATHER DETECTION
|
| 66 |
# ================================================
|
|
|
|
| 114 |
img_bgr = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR)
|
| 115 |
H, W = img_rgb.shape[:2]
|
| 116 |
|
| 117 |
+
# ---- ROAD CHECK ----
|
| 118 |
+
if not is_road_image(img_rgb):
|
| 119 |
+
fig = plt.figure(figsize=(8, 4))
|
| 120 |
+
fig.patch.set_facecolor('#0d1117')
|
| 121 |
+
ax = fig.add_subplot(111)
|
| 122 |
+
ax.set_facecolor('#161b22')
|
| 123 |
+
ax.imshow(img_rgb)
|
| 124 |
+
ax.axis('off')
|
| 125 |
+
ax.set_title(
|
| 126 |
+
'NOT A ROAD IMAGE — Please upload a road/street photo',
|
| 127 |
+
color='#ff4444', fontsize=13, fontweight='bold')
|
| 128 |
+
plt.tight_layout()
|
| 129 |
+
return fig, "This does not appear to be a road image.\nPlease upload a photo of a road or street for pothole detection."
|
| 130 |
+
|
| 131 |
weather_label, weather_warning = detect_weather(img_rgb)
|
| 132 |
|
| 133 |
tmp_path = '/tmp/input_image.png'
|
| 134 |
cv2.imwrite(tmp_path, img_bgr)
|
| 135 |
+
|
| 136 |
+
# ---- CONFIDENCE THRESHOLD = 0.5 ----
|
| 137 |
+
results = rtdetr_model(tmp_path, verbose=False, conf=0.5)
|
| 138 |
boxes = results[0].boxes
|
| 139 |
|
| 140 |
inp = transform(img_rgb).to(device)
|
|
|
|
| 152 |
if boxes is not None and len(boxes) > 0:
|
| 153 |
for i, box in enumerate(boxes.xyxy):
|
| 154 |
x1, y1, x2, y2 = map(int, box.tolist())
|
| 155 |
+
conf = float(boxes.conf[i])
|
| 156 |
+
|
| 157 |
+
# ---- SKIP LOW CONFIDENCE ----
|
| 158 |
+
if conf < 0.5:
|
| 159 |
+
continue
|
| 160 |
+
|
| 161 |
bw, bh = x2-x1, y2-y1
|
| 162 |
area_ratio = (bw * bh) / (H * W)
|
| 163 |
bw_cm = px_to_cm(bw, W)
|
|
|
|
| 169 |
severity_counts[sev] += 1
|
| 170 |
cnorm = tuple(c/255 for c in crgb)
|
| 171 |
pothole_data.append(dict(
|
| 172 |
+
id=len(pothole_data)+1, severity=sev,
|
| 173 |
confidence=conf, width_cm=bw_cm, height_cm=bh_cm,
|
| 174 |
area_cm2=bw_cm*bh_cm, area_pct=area_ratio*100,
|
| 175 |
depth_cm=depth_cm, risk=risk, color=cnorm,
|