Ayesha352 commited on
Commit
2df0729
·
verified ·
1 Parent(s): aab2e6f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -30
app.py CHANGED
@@ -3,7 +3,7 @@ import numpy as np
3
  import json
4
  import gradio as gr
5
  import os
6
- import xml.etree.ElementTree as ET
7
 
8
  # ---------------- Helper functions ----------------
9
  def get_rotated_rect_corners(x, y, w, h, rotation_deg):
@@ -36,16 +36,30 @@ def detect_and_match(img1_gray, img2_gray, method="SIFT", ratio_thresh=0.78):
36
  good = [m for m,n in raw_matches if m.distance < ratio_thresh*n.distance]
37
  return kp1, kp2, good
38
 
39
- def parse_xml_points(xml_file):
40
- tree = ET.parse(xml_file)
 
41
  root = tree.getroot()
42
- points=[]
43
- for pt_type in ["TopLeft","TopRight","BottomLeft","BottomRight"]:
44
- elem=root.find(f".//point[@type='{pt_type}']")
45
- points.append([float(elem.get("x")), float(elem.get("y"))])
46
- return np.array(points,dtype=np.float32).reshape(-1,2)
47
-
48
- # ---------------- Padding Helpers ----------------
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  def pad_to_size(img, target_h, target_w):
50
  h, w = img.shape[:2]
51
  canvas = np.ones((target_h, target_w,3), dtype=np.uint8)*255
@@ -77,7 +91,7 @@ def homography_all_detectors(flat_file, persp_file, json_file, xml_file):
77
 
78
  flat_gray = preprocess_gray_clahe(flat_img)
79
  persp_gray = preprocess_gray_clahe(persp_img)
80
- xml_points = parse_xml_points(xml_file.name)
81
 
82
  methods = ["SIFT","ORB","BRISK","KAZE","AKAZE"]
83
  gallery_paths = []
@@ -89,47 +103,42 @@ def homography_all_detectors(flat_file, persp_file, json_file, xml_file):
89
 
90
  match_img = cv2.drawMatches(flat_img,kp1,persp_img,kp2,good_matches,None,flags=2)
91
 
 
 
92
  src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1,1,2)
93
  dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1,1,2)
94
  H,_ = cv2.findHomography(src_pts,dst_pts,cv2.RANSAC,5.0)
95
- if H is None: continue
96
-
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
  persp_roi = persp_img.copy()
100
- cv2.polylines(persp_roi,[roi_corners_persp.astype(int)],True,(0,255,0),2)
101
- for px,py in roi_corners_persp: cv2.circle(persp_roi,(int(px),int(py)),5,(255,0,0),-1)
 
 
102
 
103
- xml_gt_img = persp_img.copy()
104
- xml_mapped = cv2.perspectiveTransform(xml_points.reshape(-1,1,2),H).reshape(-1,2)
105
- for px,py in xml_mapped: cv2.circle(xml_gt_img,(int(px),int(py)),5,(0,0,255),-1)
106
 
107
  # Convert to RGB
108
  flat_rgb = cv2.cvtColor(flat_img,cv2.COLOR_BGR2RGB)
109
- persp_rgb = cv2.cvtColor(persp_img,cv2.COLOR_BGR2RGB)
 
110
  roi_rgb = cv2.cvtColor(persp_roi,cv2.COLOR_BGR2RGB)
111
  xml_rgb = cv2.cvtColor(xml_gt_img,cv2.COLOR_BGR2RGB)
112
 
113
- # Resize match_img to flat image width, maintain aspect ratio
114
- match_rgb = match_img_to_reference(cv2.cvtColor(match_img, cv2.COLOR_BGR2RGB),
115
- flat_rgb.shape[0], flat_rgb.shape[1])
116
-
117
- # Determine max height and width for grid
118
  max_h = max(flat_rgb.shape[0], match_rgb.shape[0], roi_rgb.shape[0], xml_rgb.shape[0])
119
  max_w = max(flat_rgb.shape[1], match_rgb.shape[1], roi_rgb.shape[1], xml_rgb.shape[1])
120
 
121
- # Pad all images
122
  flat_pad = pad_to_size(flat_rgb, max_h, max_w)
123
  match_pad = pad_to_size(match_rgb, max_h, max_w)
124
  roi_pad = pad_to_size(roi_rgb, max_h, max_w)
125
  xml_pad = pad_to_size(xml_rgb, max_h, max_w)
126
 
127
- # Merge 2x2 grid
128
  top = np.hstack([flat_pad, match_pad])
129
  bottom = np.hstack([roi_pad, xml_pad])
130
  combined_grid = np.vstack([top, bottom])
131
 
132
- # Save combined grid
133
  base_name = os.path.splitext(os.path.basename(persp_file))[0]
134
  file_name = f"{base_name}_{method.lower()}.png"
135
  cv2.imwrite(file_name, cv2.cvtColor(combined_grid,cv2.COLOR_RGB2BGR))
@@ -157,7 +166,7 @@ iface = gr.Interface(
157
  gr.File(label="Download AKAZE Result")
158
  ],
159
  title="Homography ROI Projection with Feature Matching & XML GT",
160
- description="Flat + Perspective images with mockup.json & XML. Original resolution maintained. Grid aligned with white padding."
161
  )
162
 
163
  iface.launch()
 
3
  import json
4
  import gradio as gr
5
  import os
6
+ from lxml import etree
7
 
8
  # ---------------- Helper functions ----------------
9
  def get_rotated_rect_corners(x, y, w, h, rotation_deg):
 
36
  good = [m for m,n in raw_matches if m.distance < ratio_thresh*n.distance]
37
  return kp1, kp2, good
38
 
39
+ # ---------------- XML overlay helper using lxml ----------------
40
+ def extract_points_lxml(xml_path):
41
+ tree = etree.parse(xml_path)
42
  root = tree.getroot()
43
+ transform = root.find('.//transform')
44
+ points = {}
45
+ for pt in transform.findall('.//point'):
46
+ pt_type = pt.attrib['type']
47
+ x = float(pt.attrib['x'])
48
+ y = float(pt.attrib['y'])
49
+ points[pt_type] = (x,y)
50
+ return points
51
+
52
+ def draw_polygon_on_image(img, points_dict):
53
+ ordered_points = ['TopLeft','TopRight','BottomRight','BottomLeft']
54
+ polygon = [points_dict[pt] for pt in ordered_points]
55
+ pts = np.array(polygon, np.int32).reshape((-1,1,2))
56
+ img_copy = img.copy()
57
+ cv2.polylines(img_copy, [pts], isClosed=True, color=(0,0,255), thickness=3)
58
+ for px, py in polygon:
59
+ cv2.circle(img_copy, (int(px),int(py)), 5, (255,0,0), -1)
60
+ return img_copy
61
+
62
+ # ---------------- Padding Helper ----------------
63
  def pad_to_size(img, target_h, target_w):
64
  h, w = img.shape[:2]
65
  canvas = np.ones((target_h, target_w,3), dtype=np.uint8)*255
 
91
 
92
  flat_gray = preprocess_gray_clahe(flat_img)
93
  persp_gray = preprocess_gray_clahe(persp_img)
94
+ xml_points_dict = extract_points_lxml(xml_file.name)
95
 
96
  methods = ["SIFT","ORB","BRISK","KAZE","AKAZE"]
97
  gallery_paths = []
 
103
 
104
  match_img = cv2.drawMatches(flat_img,kp1,persp_img,kp2,good_matches,None,flags=2)
105
 
106
+ # ROI on perspective image
107
+ roi_corners_flat = get_rotated_rect_corners(roi_x,roi_y,roi_w,roi_h,roi_rot_deg)
108
  src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1,1,2)
109
  dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1,1,2)
110
  H,_ = cv2.findHomography(src_pts,dst_pts,cv2.RANSAC,5.0)
 
 
 
 
111
  persp_roi = persp_img.copy()
112
+ if H is not None:
113
+ roi_corners_persp = cv2.perspectiveTransform(roi_corners_flat.reshape(-1,1,2),H).reshape(-1,2)
114
+ cv2.polylines(persp_roi,[roi_corners_persp.astype(int)],True,(0,255,0),2)
115
+ for px,py in roi_corners_persp: cv2.circle(persp_roi,(int(px),int(py)),5,(255,0,0),-1)
116
 
117
+ # XML GT overlay on perspective
118
+ xml_gt_img = draw_polygon_on_image(persp_img, xml_points_dict)
 
119
 
120
  # Convert to RGB
121
  flat_rgb = cv2.cvtColor(flat_img,cv2.COLOR_BGR2RGB)
122
+ match_rgb = match_img_to_reference(cv2.cvtColor(match_img,cv2.COLOR_BGR2RGB),
123
+ flat_rgb.shape[0], flat_rgb.shape[1])
124
  roi_rgb = cv2.cvtColor(persp_roi,cv2.COLOR_BGR2RGB)
125
  xml_rgb = cv2.cvtColor(xml_gt_img,cv2.COLOR_BGR2RGB)
126
 
127
+ # Determine max height and width
 
 
 
 
128
  max_h = max(flat_rgb.shape[0], match_rgb.shape[0], roi_rgb.shape[0], xml_rgb.shape[0])
129
  max_w = max(flat_rgb.shape[1], match_rgb.shape[1], roi_rgb.shape[1], xml_rgb.shape[1])
130
 
131
+ # Pad images
132
  flat_pad = pad_to_size(flat_rgb, max_h, max_w)
133
  match_pad = pad_to_size(match_rgb, max_h, max_w)
134
  roi_pad = pad_to_size(roi_rgb, max_h, max_w)
135
  xml_pad = pad_to_size(xml_rgb, max_h, max_w)
136
 
137
+ # 2x2 grid
138
  top = np.hstack([flat_pad, match_pad])
139
  bottom = np.hstack([roi_pad, xml_pad])
140
  combined_grid = np.vstack([top, bottom])
141
 
 
142
  base_name = os.path.splitext(os.path.basename(persp_file))[0]
143
  file_name = f"{base_name}_{method.lower()}.png"
144
  cv2.imwrite(file_name, cv2.cvtColor(combined_grid,cv2.COLOR_RGB2BGR))
 
166
  gr.File(label="Download AKAZE Result")
167
  ],
168
  title="Homography ROI Projection with Feature Matching & XML GT",
169
+ description="Flat + Perspective images with mockup.json & XML. Grid aligned. Perspective GT overlay now uses XML lxml parsing."
170
  )
171
 
172
  iface.launch()