umairahmad1789 commited on
Commit
3a66ca9
1 Parent(s): 8ca529b

Update scalingtestupdated.py

Browse files
Files changed (1) hide show
  1. scalingtestupdated.py +180 -167
scalingtestupdated.py CHANGED
@@ -1,167 +1,180 @@
1
- import cv2
2
- import numpy as np
3
- import os
4
- import argparse
5
- from typing import Union
6
- from matplotlib import pyplot as plt
7
-
8
-
9
- class ScalingSquareDetector:
10
- def __init__(self, feature_detector="ORB", debug=False):
11
- """
12
- Initialize the detector with the desired feature matching algorithm.
13
- :param feature_detector: "ORB" or "SIFT" (default is "ORB").
14
- :param debug: If True, saves intermediate images for debugging.
15
- """
16
- self.feature_detector = feature_detector
17
- self.debug = debug
18
- self.detector = self._initialize_detector()
19
-
20
- def _initialize_detector(self):
21
- """
22
- Initialize the chosen feature detector.
23
- :return: OpenCV detector object.
24
- """
25
- if self.feature_detector.upper() == "SIFT":
26
- return cv2.SIFT_create()
27
- elif self.feature_detector.upper() == "ORB":
28
- return cv2.ORB_create()
29
- else:
30
- raise ValueError("Invalid feature detector. Choose 'ORB' or 'SIFT'.")
31
-
32
- def find_scaling_square(
33
- self, reference_image_path, target_image, known_size_mm, roi_margin=30
34
- ):
35
- """
36
- Detect the scaling square in the target image based on the reference image.
37
- :param reference_image_path: Path to the reference image of the square.
38
- :param target_image_path: Path to the target image containing the square.
39
- :param known_size_mm: Physical size of the square in millimeters.
40
- :param roi_margin: Margin to expand the ROI around the detected square (in pixels).
41
- :return: Scaling factor (mm per pixel).
42
- """
43
- target_image = cv2.cvtColor(target_image, cv2.COLOR_RGB2GRAY)
44
-
45
- roi = target_image.copy()
46
- # Find contours in the ROI
47
- roi_blurred = cv2.GaussianBlur(roi, (5, 5), 0)
48
- _, roi_binary = cv2.threshold(
49
- roi_blurred, 128, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU
50
- )
51
- contours, _ = cv2.findContours(
52
- roi_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
53
- )
54
-
55
- if not contours:
56
- raise ValueError("No contours found in the cropped ROI.")
57
-
58
- # Select the largest square-like contour
59
- largest_square = None
60
- largest_square_area = 0
61
- for contour in contours:
62
- x_c, y_c, w_c, h_c = cv2.boundingRect(contour)
63
- aspect_ratio = w_c / float(h_c)
64
- if 0.9 <= aspect_ratio <= 1.1:
65
- peri = cv2.arcLength(contour, True)
66
- approx = cv2.approxPolyDP(contour, 0.02 * peri, True)
67
- if len(approx) == 4:
68
- area = cv2.contourArea(contour)
69
- if area > largest_square_area:
70
- largest_square = contour
71
- largest_square_area = area
72
-
73
- if largest_square is None:
74
- raise ValueError("No square-like contour found in the ROI.")
75
-
76
- # Draw the largest contour on the original image
77
- target_image_color = cv2.cvtColor(target_image, cv2.COLOR_GRAY2BGR)
78
- cv2.drawContours(
79
- target_image_color, largest_square, -1, (255, 0, 0), 3
80
- )
81
-
82
- if self.debug:
83
- cv2.imwrite("largest_contour.jpg", target_image_color)
84
-
85
- # Calculate the bounding rectangle of the largest contour
86
- x, y, w, h = cv2.boundingRect(largest_square)
87
- square_width_px = w
88
- square_height_px = h
89
-
90
- # Calculate the scaling factor
91
- avg_square_size_px = (square_width_px + square_height_px) / 2
92
- scaling_factor = known_size_mm / avg_square_size_px # mm per pixel
93
-
94
- return scaling_factor
95
-
96
- def draw_debug_images(self, output_folder):
97
- """
98
- Save debug images if enabled.
99
- :param output_folder: Directory to save debug images.
100
- """
101
- if self.debug:
102
- if not os.path.exists(output_folder):
103
- os.makedirs(output_folder)
104
- debug_images = ["largest_contour.jpg"]
105
- for img_name in debug_images:
106
- if os.path.exists(img_name):
107
- os.rename(img_name, os.path.join(output_folder, img_name))
108
-
109
-
110
- def calculate_scaling_factor(
111
- reference_image_path,
112
- target_image,
113
- known_square_size_mm=9.0,
114
- feature_detector="ORB",
115
- debug=False,
116
- roi_margin=30,
117
- ):
118
- # Initialize detector
119
- detector = ScalingSquareDetector(feature_detector=feature_detector, debug=debug)
120
-
121
- # Find scaling square and calculate scaling factor
122
- scaling_factor = detector.find_scaling_square(
123
- reference_image_path=reference_image_path,
124
- target_image=target_image,
125
- known_size_mm=known_square_size_mm,
126
- roi_margin=roi_margin,
127
- )
128
-
129
- # Save debug images
130
- if debug:
131
- detector.draw_debug_images("debug_outputs")
132
-
133
- return scaling_factor
134
-
135
-
136
- # Example usage:
137
- if __name__ == "__main__":
138
- import os
139
- from PIL import Image
140
- from ultralytics import YOLO
141
- from app import yolo_detect, shrink_bbox
142
- from ultralytics.utils.plotting import save_one_box
143
-
144
- for idx, file in enumerate(os.listdir("./sample_images")):
145
- img = np.array(Image.open(os.path.join("./sample_images", file)))
146
- img = yolo_detect(img, ['box'])
147
- model = YOLO("./runs/detect/train/weights/last.pt")
148
- res = model.predict(img, conf=0.6)
149
-
150
- box_img = save_one_box(res[0].cpu().boxes.xyxy, im=res[0].orig_img, save=False)
151
- img = shrink_bbox(box_img, 1.20)
152
- cv2.imwrite(f"./outputs/{idx}_{file}", img)
153
- try:
154
-
155
- scaling_factor = calculate_scaling_factor(
156
- reference_image_path="./Reference_ScalingBox.jpg",
157
- target_image=img,
158
- known_square_size_mm=9.0,
159
- feature_detector="ORB",
160
- debug=False,
161
- roi_margin=90,
162
- )
163
- print(f"Scaling Factor (mm per pixel): {scaling_factor:.6f}")
164
- except Exception as e:
165
- from traceback import print_exc
166
- print(print_exc())
167
- print(f"Error: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ import os
4
+ import argparse
5
+ from typing import Union
6
+ from matplotlib import pyplot as plt
7
+
8
+
9
+ class ScalingSquareDetector:
10
+ def __init__(self, feature_detector="ORB", debug=False):
11
+ """
12
+ Initialize the detector with the desired feature matching algorithm.
13
+ :param feature_detector: "ORB" or "SIFT" (default is "ORB").
14
+ :param debug: If True, saves intermediate images for debugging.
15
+ """
16
+ self.feature_detector = feature_detector
17
+ self.debug = debug
18
+ self.detector = self._initialize_detector()
19
+
20
+ def _initialize_detector(self):
21
+ """
22
+ Initialize the chosen feature detector.
23
+ :return: OpenCV detector object.
24
+ """
25
+ if self.feature_detector.upper() == "SIFT":
26
+ return cv2.SIFT_create()
27
+ elif self.feature_detector.upper() == "ORB":
28
+ return cv2.ORB_create()
29
+ else:
30
+ raise ValueError("Invalid feature detector. Choose 'ORB' or 'SIFT'.")
31
+
32
+ def find_scaling_square(
33
+ self, reference_image_path, target_image, known_size_mm, roi_margin=30
34
+ ):
35
+ """
36
+ Detect the scaling square in the target image based on the reference image.
37
+ :param reference_image_path: Path to the reference image of the square.
38
+ :param target_image_path: Path to the target image containing the square.
39
+ :param known_size_mm: Physical size of the square in millimeters.
40
+ :param roi_margin: Margin to expand the ROI around the detected square (in pixels).
41
+ :return: Scaling factor (mm per pixel).
42
+ """
43
+
44
+ contours, _ = cv2.findContours(
45
+ target_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE
46
+ )
47
+
48
+ if not contours:
49
+ raise ValueError("No contours found in the cropped ROI.")
50
+
51
+ # # Select the largest square-like contour
52
+ largest_square = None
53
+ largest_square_area = 0
54
+ for contour in contours:
55
+ x_c, y_c, w_c, h_c = cv2.boundingRect(contour)
56
+ aspect_ratio = w_c / float(h_c)
57
+ if 0.9 <= aspect_ratio <= 1.1:
58
+ peri = cv2.arcLength(contour, True)
59
+ approx = cv2.approxPolyDP(contour, 0.02 * peri, True)
60
+ if len(approx) == 4:
61
+ area = cv2.contourArea(contour)
62
+ if area > largest_square_area:
63
+ largest_square = contour
64
+ largest_square_area = area
65
+
66
+ # if largest_square is None:
67
+ # raise ValueError("No square-like contour found in the ROI.")
68
+
69
+ # Draw the largest contour on the original image
70
+ target_image_color = cv2.cvtColor(target_image, cv2.COLOR_GRAY2BGR)
71
+ cv2.drawContours(
72
+ target_image_color, largest_square, -1, (255, 0, 0), 3
73
+ )
74
+
75
+ # if self.debug:
76
+ cv2.imwrite("largest_contour.jpg", target_image_color)
77
+
78
+ # Calculate the bounding rectangle of the largest contour
79
+ x, y, w, h = cv2.boundingRect(largest_square)
80
+ square_width_px = w
81
+ square_height_px = h
82
+
83
+ # Calculate the scaling factor
84
+ avg_square_size_px = (square_width_px + square_height_px) / 2
85
+ scaling_factor = 0.5 / avg_square_size_px # mm per pixel
86
+
87
+ return scaling_factor #, square_height_px, square_width_px, roi_binary
88
+
89
+ def draw_debug_images(self, output_folder):
90
+ """
91
+ Save debug images if enabled.
92
+ :param output_folder: Directory to save debug images.
93
+ """
94
+ if self.debug:
95
+ if not os.path.exists(output_folder):
96
+ os.makedirs(output_folder)
97
+ debug_images = ["largest_contour.jpg"]
98
+ for img_name in debug_images:
99
+ if os.path.exists(img_name):
100
+ os.rename(img_name, os.path.join(output_folder, img_name))
101
+
102
+
103
+ def calculate_scaling_factor(
104
+ reference_image_path,
105
+ target_image,
106
+ known_square_size_mm=12.7,
107
+ feature_detector="ORB",
108
+ debug=False,
109
+ roi_margin=30,
110
+ ):
111
+ # Initialize detector
112
+ detector = ScalingSquareDetector(feature_detector=feature_detector, debug=debug)
113
+
114
+ # Find scaling square and calculate scaling factor
115
+ scaling_factor = detector.find_scaling_square(
116
+ reference_image_path=reference_image_path,
117
+ target_image=target_image,
118
+ known_size_mm=known_square_size_mm,
119
+ roi_margin=roi_margin,
120
+ )
121
+
122
+ # Save debug images
123
+ if debug:
124
+ detector.draw_debug_images("debug_outputs")
125
+
126
+ return scaling_factor
127
+
128
+
129
+ # Example usage:
130
+ if __name__ == "__main__":
131
+ import os
132
+ from PIL import Image
133
+ from ultralytics import YOLO
134
+ from app import yolo_detect, shrink_bbox
135
+ from ultralytics.utils.plotting import save_one_box
136
+
137
+ for idx, file in enumerate(os.listdir("./sample_images")):
138
+ img = np.array(Image.open(os.path.join("./sample_images", file)))
139
+ img = yolo_detect(img, ['box'])
140
+ model = YOLO("./last.pt")
141
+ res = model.predict(img, conf=0.6)
142
+
143
+ box_img = save_one_box(res[0].cpu().boxes.xyxy, im=res[0].orig_img, save=False)
144
+ # img = shrink_bbox(box_img, 1.20)
145
+ cv2.imwrite(f"./outputs/{idx}_{file}", box_img)
146
+
147
+ print("File: ",f"./outputs/{idx}_{file}")
148
+ try:
149
+
150
+ scaling_factor = calculate_scaling_factor(
151
+ reference_image_path="./Reference_ScalingBox.jpg",
152
+ target_image=box_img,
153
+ known_square_size_mm=12.7,
154
+ feature_detector="ORB",
155
+ debug=False,
156
+ roi_margin=90,
157
+ )
158
+ # cv2.imwrite(f"./outputs/{idx}_binary_{file}", roi_binary)
159
+
160
+ # Square size in mm
161
+ # square_size_mm = 12.7
162
+
163
+ # # Compute the calculated scaling factors and compare
164
+ # calculated_scaling_factor = square_size_mm / height_px
165
+ # discrepancy = abs(calculated_scaling_factor - scaling_factor)
166
+ # import pprint
167
+ # pprint.pprint({
168
+ # "height_px": height_px,
169
+ # "width_px": width_px,
170
+ # "given_scaling_factor": scaling_factor,
171
+ # "calculated_scaling_factor": calculated_scaling_factor,
172
+ # "discrepancy": discrepancy,
173
+ # })
174
+
175
+
176
+ print(f"Scaling Factor (mm per pixel): {scaling_factor:.6f}")
177
+ except Exception as e:
178
+ from traceback import print_exc
179
+ print(print_exc())
180
+ print(f"Error: {e}")