Spaces:
Sleeping
Sleeping
File size: 4,571 Bytes
0d72d25 b4ecde4 0d72d25 b4ecde4 5138913 b4ecde4 5138913 b4ecde4 5138913 b4ecde4 5138913 b4ecde4 0d72d25 b4ecde4 5138913 b4ecde4 5138913 b4ecde4 5138913 b4ecde4 5138913 b4ecde4 5138913 b4ecde4 5138913 b4ecde4 0d72d25 5138913 b4ecde4 5138913 b4ecde4 5138913 b4ecde4 5138913 438fcec 0d72d25 b4ecde4 dd80a33 03915c5 b4ecde4 0d72d25 b4ecde4 | 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 gradio as gr
import cv2
import numpy as np
import matplotlib.pyplot as plt
import json
import math
# === Helper: Rotated rectangle corners ===
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)
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]
])
R = np.array([[cos_r, -sin_r],
[sin_r, cos_r]])
rotated_corners = np.dot(local_corners, R.T)
corners = rotated_corners + np.array([cx, cy])
return corners.astype(np.float32)
# === Preprocessing ===
def preprocess_gray_clahe(img):
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))
return clahe.apply(gray)
# === Feature detectors ===
def get_detector(detector_name):
if detector_name == "SIFT":
return cv2.SIFT_create(nfeatures=5000)
elif detector_name == "ORB":
return cv2.ORB_create(5000)
elif detector_name == "BRISK":
return cv2.BRISK_create()
elif detector_name == "AKAZE":
return cv2.AKAZE_create()
elif detector_name == "KAZE":
return cv2.KAZE_create()
else:
return None
def detect_and_match(img1_gray, img2_gray, detector_name, ratio_thresh=0.78):
detector = get_detector(detector_name)
kp1, des1 = detector.detectAndCompute(img1_gray, None)
kp2, des2 = detector.detectAndCompute(img2_gray, None)
if detector_name in ["SIFT", "KAZE"]:
matcher = cv2.BFMatcher(cv2.NORM_L2)
else:
matcher = cv2.BFMatcher(cv2.NORM_HAMMING)
matches = matcher.knnMatch(des1, des2, k=2)
good = []
for m, n in matches:
if m.distance < ratio_thresh * n.distance:
good.append(m)
return kp1, kp2, good
# === Main processing ===
def process_images(flat_img, persp_img, json_file):
if flat_img is None or persp_img is None or json_file is None:
return [None]*6
# Load JSON
try:
data = json.load(open(json_file.name))
except Exception as e:
print("JSON read error:", e)
return [None]*6
roi = data["printAreas"][0]
roi_x = roi["position"]["x"]
roi_y = roi["position"]["y"]
roi_w = roi["width"]
roi_h = roi["height"]
roi_rot_deg = roi["rotation"]
# Preprocess images
flat_gray = preprocess_gray_clahe(flat_img)
persp_gray = preprocess_gray_clahe(persp_img)
detectors = ["SIFT", "ORB", "BRISK", "AKAZE", "KAZE"]
results = []
for det in detectors:
kp1, kp2, good_matches = detect_and_match(flat_gray, persp_gray, det)
if len(good_matches) < 4:
print(f"Not enough matches for {det}")
results.append(None)
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)
# ROI corners
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)
# Draw ROI
flat_out = flat_img.copy()
persp_out = persp_img.copy()
cv2.polylines(flat_out, [roi_corners_flat.astype(int)], True, (255,0,0), 3)
cv2.polylines(persp_out, [roi_corners_persp.astype(int)], True, (0,255,0), 3)
results.append([flat_out, persp_out])
return results # List of [flat_out, persp_out] for each detector
# === Gradio Interface ===
def wrap_gradio(flat_img, persp_img, json_file):
outputs = process_images(flat_img, persp_img, json_file)
# Flatten the outputs for Gallery display
gallery_images = []
for item in outputs:
if item is not None:
gallery_images.extend([item[0], item[1]])
return gallery_images
iface = gr.Interface(
fn=wrap_gradio,
inputs=[
gr.Image(type="numpy", label="Flat Image"),
gr.Image(type="numpy", label="Perspective Image"),
gr.File(type="filepath", label="JSON File")
],
outputs=[
gr.Gallery(label="Results (Flat + Perspective per Detector)")
],
title="Feature Detection with ROI Projection",
description="Shows SIFT, ORB, BRISK, AKAZE, KAZE feature-based ROI projections. Each detector outputs Flat and Perspective images."
)
iface.launch()
|