Spaces:
Sleeping
Sleeping
File size: 5,358 Bytes
0d72d25 666ed4b 0d72d25 bf80eca 5138913 666ed4b b4ecde4 666ed4b b4ecde4 666ed4b b4ecde4 5138913 666ed4b b4ecde4 5138913 666ed4b b4ecde4 666ed4b b4ecde4 666ed4b b4ecde4 5138913 bf80eca 666ed4b bf80eca 5138913 bf80eca 0d72d25 bf80eca 666ed4b 0ffe5fa b057173 b4ecde4 5138913 0ffe5fa b4ecde4 b057173 f644374 bf80eca b057173 666ed4b b057173 b4ecde4 bf80eca | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | import cv2
import numpy as np
import json
import gradio as gr
# ---------------- Your Original Functions (Unchanged) ---------------- #
def get_rotated_rect_corners(x, y, w, h, rotation_deg):
rot_rad = np.deg2rad(rotation_deg)
cos_r = np.cos(rot_rad)
sin_r = np.sin(rot_rad)
R = np.array([[cos_r, -sin_r],
[sin_r, cos_r]])
cx = x + w/2
cy = y + h/2
local_corners = np.array([
[-w/2, -h/2],
[ w/2, -h/2],
[ w/2, h/2],
[-w/2, h/2]
])
rotated_corners = np.dot(local_corners, R.T)
corners = rotated_corners + np.array([cx, cy])
return corners.astype(np.float32)
def preprocess_gray_clahe(img):
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))
return clahe.apply(gray)
def detect_and_match(img1_gray, img2_gray, method="SIFT", ratio_thresh=0.78):
if method == "SIFT":
sift = cv2.SIFT_create(nfeatures=5000)
kp1, des1 = sift.detectAndCompute(img1_gray, None)
kp2, des2 = sift.detectAndCompute(img2_gray, None)
matcher = cv2.BFMatcher(cv2.NORM_L2)
elif method == "ORB":
orb = cv2.ORB_create(5000)
kp1, des1 = orb.detectAndCompute(img1_gray, None)
kp2, des2 = orb.detectAndCompute(img2_gray, None)
matcher = cv2.BFMatcher(cv2.NORM_HAMMING)
elif method == "BRISK":
brisk = cv2.BRISK_create()
kp1, des1 = brisk.detectAndCompute(img1_gray, None)
kp2, des2 = brisk.detectAndCompute(img2_gray, None)
matcher = cv2.BFMatcher(cv2.NORM_HAMMING)
elif method == "KAZE":
kaze = cv2.KAZE_create()
kp1, des1 = kaze.detectAndCompute(img1_gray, None)
kp2, des2 = kaze.detectAndCompute(img2_gray, None)
matcher = cv2.BFMatcher(cv2.NORM_L2)
elif method == "AKAZE":
akaze = cv2.AKAZE_create()
kp1, des1 = akaze.detectAndCompute(img1_gray, None)
kp2, des2 = akaze.detectAndCompute(img2_gray, None)
matcher = cv2.BFMatcher(cv2.NORM_HAMMING)
else:
return None, None, None
raw_matches = matcher.knnMatch(des1, des2, k=2)
good = []
for m, n in raw_matches:
if m.distance < ratio_thresh * n.distance:
good.append(m)
return kp1, kp2, good
# ---------------- Processing Function for Gradio ---------------- #
def homography_all_detectors(flat_img, persp_img, json_file):
if flat_img is None or persp_img is None:
return [None] * 6
flat_bgr = cv2.cvtColor(flat_img, cv2.COLOR_RGB2BGR)
persp_bgr = cv2.cvtColor(persp_img, cv2.COLOR_RGB2BGR)
with open(json_file.name, 'r') as f:
mockup = json.load(f)
roi_data = mockup["printAreas"][0]["position"]
roi_x = roi_data["x"]
roi_y = roi_data["y"]
roi_w = mockup["printAreas"][0]["width"]
roi_h = mockup["printAreas"][0]["height"]
roi_rot_deg = mockup["printAreas"][0]["rotation"]
flat_gray = preprocess_gray_clahe(flat_bgr)
persp_gray = preprocess_gray_clahe(persp_bgr)
detectors = ["SIFT", "ORB", "BRISK", "KAZE", "AKAZE"]
gallery_images = []
download_files = [None] * 5
for i, method in enumerate(detectors):
kp1, kp2, good_matches = detect_and_match(flat_gray, persp_gray, method=method)
if kp1 is None or kp2 is None or len(good_matches) < 4:
continue
src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1,1,2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1,1,2)
H, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
if H is None:
continue
roi_corners_flat = get_rotated_rect_corners(roi_x, roi_y, roi_w, roi_h, roi_rot_deg)
roi_corners_persp = cv2.perspectiveTransform(roi_corners_flat.reshape(-1,1,2), H).reshape(-1,2)
persp_debug = persp_bgr.copy()
cv2.polylines(persp_debug, [roi_corners_persp.astype(int)], True, (0,255,0), 2)
for (px, py) in roi_corners_persp:
cv2.circle(persp_debug, (int(px), int(py)), 5, (255,0,0), -1)
result_rgb = cv2.cvtColor(persp_debug, cv2.COLOR_BGR2RGB)
file_name = f"result_{method.lower()}.png"
cv2.imwrite(file_name, result_rgb[:, :, ::-1]) # save as BGR
gallery_images.append((f"{method} Result", result_rgb))
download_files[i] = file_name
return [gallery_images] + download_files
# ---------------- Gradio Interface ---------------- #
iface = gr.Interface(
fn=homography_all_detectors,
inputs=[
gr.Image(type="numpy", label="Image 1 (Flat)"),
gr.Image(type="numpy", label="Image 2 (Perspective)"),
gr.File(type="filepath", label="JSON File")
],
outputs=[
gr.Gallery(label="Results"),
gr.File(label="Download SIFT Result"),
gr.File(label="Download ORB Result"),
gr.File(label="Download BRISK Result"),
gr.File(label="Download KAZE Result"),
gr.File(label="Download AKAZE Result")
],
title="Homography ROI Projection with Multiple Feature Detectors",
description="Upload a flat image, a perspective image, and the JSON file. The system will compute homography with SIFT, ORB, BRISK, KAZE, and AKAZE, project the bounding box, and allow result download."
)
iface.launch()
|