Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -9,20 +9,16 @@ def get_rotated_rect_corners(x, y, w, h, rotation_deg):
|
|
| 9 |
rot_rad = np.deg2rad(rotation_deg)
|
| 10 |
cos_r = np.cos(rot_rad)
|
| 11 |
sin_r = np.sin(rot_rad)
|
| 12 |
-
|
| 13 |
cx = x + w/2
|
| 14 |
cy = y + h/2
|
| 15 |
-
|
| 16 |
local_corners = np.array([
|
| 17 |
[-w/2, -h/2],
|
| 18 |
[ w/2, -h/2],
|
| 19 |
[ w/2, h/2],
|
| 20 |
[-w/2, h/2]
|
| 21 |
])
|
| 22 |
-
|
| 23 |
R = np.array([[cos_r, -sin_r],
|
| 24 |
[sin_r, cos_r]])
|
| 25 |
-
|
| 26 |
rotated_corners = np.dot(local_corners, R.T)
|
| 27 |
corners = rotated_corners + np.array([cx, cy])
|
| 28 |
return corners.astype(np.float32)
|
|
@@ -52,17 +48,12 @@ def detect_and_match(img1_gray, img2_gray, detector_name, ratio_thresh=0.78):
|
|
| 52 |
detector = get_detector(detector_name)
|
| 53 |
kp1, des1 = detector.detectAndCompute(img1_gray, None)
|
| 54 |
kp2, des2 = detector.detectAndCompute(img2_gray, None)
|
| 55 |
-
|
| 56 |
if detector_name in ["SIFT", "KAZE"]:
|
| 57 |
matcher = cv2.BFMatcher(cv2.NORM_L2)
|
| 58 |
else:
|
| 59 |
matcher = cv2.BFMatcher(cv2.NORM_HAMMING)
|
| 60 |
-
|
| 61 |
matches = matcher.knnMatch(des1, des2, k=2)
|
| 62 |
-
good = []
|
| 63 |
-
for m, n in matches:
|
| 64 |
-
if m.distance < ratio_thresh * n.distance:
|
| 65 |
-
good.append(m)
|
| 66 |
return kp1, kp2, good
|
| 67 |
|
| 68 |
# === Main processing ===
|
|
@@ -106,19 +97,14 @@ def process_images(flat_img, persp_img, json_file):
|
|
| 106 |
roi_corners_flat = get_rotated_rect_corners(roi_x, roi_y, roi_w, roi_h, roi_rot_deg)
|
| 107 |
roi_corners_persp = cv2.perspectiveTransform(roi_corners_flat.reshape(-1,1,2), H).reshape(-1,2)
|
| 108 |
|
| 109 |
-
# Draw ROI & label
|
| 110 |
-
flat_out = flat_img.copy()
|
| 111 |
persp_out = persp_img.copy()
|
| 112 |
-
cv2.polylines(flat_out, [roi_corners_flat.astype(int)], True, (255,0,0), 3)
|
| 113 |
cv2.polylines(persp_out, [roi_corners_persp.astype(int)], True, (0,255,0), 3)
|
| 114 |
-
cv2.putText(flat_out, det, (10,30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,255), 2)
|
| 115 |
cv2.putText(persp_out, det, (10,30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,255), 2)
|
| 116 |
|
| 117 |
# Convert to RGB for Gradio
|
| 118 |
-
flat_rgb = cv2.cvtColor(flat_out, cv2.COLOR_BGR2RGB)
|
| 119 |
persp_rgb = cv2.cvtColor(persp_out, cv2.COLOR_BGR2RGB)
|
| 120 |
-
|
| 121 |
-
gallery_images.extend([flat_rgb, persp_rgb])
|
| 122 |
|
| 123 |
return gallery_images
|
| 124 |
|
|
@@ -131,10 +117,10 @@ iface = gr.Interface(
|
|
| 131 |
gr.File(type="filepath", label="JSON File")
|
| 132 |
],
|
| 133 |
outputs=[
|
| 134 |
-
gr.Gallery(label="Detector Results (
|
| 135 |
],
|
| 136 |
-
title="Feature Detection
|
| 137 |
-
description="Shows SIFT, ORB, BRISK, AKAZE, KAZE
|
| 138 |
)
|
| 139 |
|
| 140 |
iface.launch()
|
|
|
|
| 9 |
rot_rad = np.deg2rad(rotation_deg)
|
| 10 |
cos_r = np.cos(rot_rad)
|
| 11 |
sin_r = np.sin(rot_rad)
|
|
|
|
| 12 |
cx = x + w/2
|
| 13 |
cy = y + h/2
|
|
|
|
| 14 |
local_corners = np.array([
|
| 15 |
[-w/2, -h/2],
|
| 16 |
[ w/2, -h/2],
|
| 17 |
[ w/2, h/2],
|
| 18 |
[-w/2, h/2]
|
| 19 |
])
|
|
|
|
| 20 |
R = np.array([[cos_r, -sin_r],
|
| 21 |
[sin_r, cos_r]])
|
|
|
|
| 22 |
rotated_corners = np.dot(local_corners, R.T)
|
| 23 |
corners = rotated_corners + np.array([cx, cy])
|
| 24 |
return corners.astype(np.float32)
|
|
|
|
| 48 |
detector = get_detector(detector_name)
|
| 49 |
kp1, des1 = detector.detectAndCompute(img1_gray, None)
|
| 50 |
kp2, des2 = detector.detectAndCompute(img2_gray, None)
|
|
|
|
| 51 |
if detector_name in ["SIFT", "KAZE"]:
|
| 52 |
matcher = cv2.BFMatcher(cv2.NORM_L2)
|
| 53 |
else:
|
| 54 |
matcher = cv2.BFMatcher(cv2.NORM_HAMMING)
|
|
|
|
| 55 |
matches = matcher.knnMatch(des1, des2, k=2)
|
| 56 |
+
good = [m for m,n in matches if m.distance < ratio_thresh*n.distance]
|
|
|
|
|
|
|
|
|
|
| 57 |
return kp1, kp2, good
|
| 58 |
|
| 59 |
# === Main processing ===
|
|
|
|
| 97 |
roi_corners_flat = get_rotated_rect_corners(roi_x, roi_y, roi_w, roi_h, roi_rot_deg)
|
| 98 |
roi_corners_persp = cv2.perspectiveTransform(roi_corners_flat.reshape(-1,1,2), H).reshape(-1,2)
|
| 99 |
|
| 100 |
+
# Draw ROI & detector label on perspective image only
|
|
|
|
| 101 |
persp_out = persp_img.copy()
|
|
|
|
| 102 |
cv2.polylines(persp_out, [roi_corners_persp.astype(int)], True, (0,255,0), 3)
|
|
|
|
| 103 |
cv2.putText(persp_out, det, (10,30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,255), 2)
|
| 104 |
|
| 105 |
# Convert to RGB for Gradio
|
|
|
|
| 106 |
persp_rgb = cv2.cvtColor(persp_out, cv2.COLOR_BGR2RGB)
|
| 107 |
+
gallery_images.append(persp_rgb)
|
|
|
|
| 108 |
|
| 109 |
return gallery_images
|
| 110 |
|
|
|
|
| 117 |
gr.File(type="filepath", label="JSON File")
|
| 118 |
],
|
| 119 |
outputs=[
|
| 120 |
+
gr.Gallery(label="Detector Results (Perspective Images with ROI & Label)")
|
| 121 |
],
|
| 122 |
+
title="Feature Detection ROI Projection",
|
| 123 |
+
description="Shows SIFT, ORB, BRISK, AKAZE, KAZE detector results on the Perspective image only, with ROI and detector label."
|
| 124 |
)
|
| 125 |
|
| 126 |
iface.launch()
|