Update app.py
Browse files
app.py
CHANGED
|
@@ -75,7 +75,7 @@ def custom_nms(preds, iou_threshold=0.3):
|
|
| 75 |
return filtered_preds
|
| 76 |
|
| 77 |
#########################################
|
| 78 |
-
# 3. Processing Function with
|
| 79 |
#########################################
|
| 80 |
|
| 81 |
def process_image(job_id, image_path, object_type):
|
|
@@ -109,12 +109,12 @@ def process_image(job_id, image_path, object_type):
|
|
| 109 |
for prediction in predictions:
|
| 110 |
try:
|
| 111 |
x, y, width, height = prediction["x"], prediction["y"], prediction["width"], prediction["height"]
|
| 112 |
-
# Convert center x,y and width, height to top-left
|
| 113 |
x1 = int(round(x - width / 2))
|
| 114 |
y1 = int(round(y - height / 2))
|
| 115 |
x2 = int(round(x + width / 2))
|
| 116 |
y2 = int(round(y + height / 2))
|
| 117 |
-
# Clamp coordinates to
|
| 118 |
x1 = max(0, min(x1, img_width - 1))
|
| 119 |
y1 = max(0, min(y1, img_height - 1))
|
| 120 |
x2 = max(0, min(x2, img_width - 1))
|
|
@@ -128,74 +128,74 @@ def process_image(job_id, image_path, object_type):
|
|
| 128 |
continue
|
| 129 |
|
| 130 |
box_detections = custom_nms(processed_preds, iou_threshold=0.3)
|
| 131 |
-
jobs[job_id]['progress'] =
|
| 132 |
|
| 133 |
# -------------------------------
|
| 134 |
-
#
|
|
|
|
|
|
|
|
|
|
| 135 |
# -------------------------------
|
| 136 |
-
|
| 137 |
-
marker_real_width_cm = 10.0
|
| 138 |
-
homography = None
|
| 139 |
-
conversion_factor = None
|
| 140 |
try:
|
| 141 |
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
| 142 |
aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)
|
| 143 |
-
# Use DetectorParameters_create if available (for newer OpenCV versions)
|
| 144 |
if hasattr(cv2.aruco, 'DetectorParameters_create'):
|
| 145 |
aruco_params = cv2.aruco.DetectorParameters_create()
|
| 146 |
else:
|
| 147 |
aruco_params = cv2.aruco.DetectorParameters()
|
| 148 |
corners, ids, _ = cv2.aruco.detectMarkers(gray, aruco_dict, parameters=aruco_params)
|
| 149 |
if ids is not None and len(corners) > 0:
|
| 150 |
-
# Use the first detected marker
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
#
|
| 162 |
-
|
| 163 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
else:
|
| 165 |
-
|
| 166 |
-
conversion_factor = None
|
| 167 |
except Exception as e:
|
| 168 |
-
|
| 169 |
-
|
|
|
|
| 170 |
|
| 171 |
-
# Process each detected box
|
| 172 |
for pred in box_detections:
|
| 173 |
x1, y1, x2, y2 = pred["box"]
|
| 174 |
label = pred["class"]
|
| 175 |
confidence = pred["confidence"]
|
| 176 |
cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
|
| 177 |
-
|
| 178 |
-
if homography is not None and conversion_factor is not None:
|
| 179 |
-
# Warp the four corners of the bounding box using the homography
|
| 180 |
-
pts = np.array([[x1, y1],
|
| 181 |
-
[x2, y1],
|
| 182 |
-
[x2, y2],
|
| 183 |
-
[x1, y2]], dtype=np.float32).reshape(-1, 1, 2)
|
| 184 |
-
warped_pts = cv2.perspectiveTransform(pts, homography).reshape(-1, 2)
|
| 185 |
-
new_x1, new_y1 = np.min(warped_pts, axis=0)
|
| 186 |
-
new_x2, new_y2 = np.max(warped_pts, axis=0)
|
| 187 |
-
box_width_pixels = new_x2 - new_x1
|
| 188 |
-
box_height_pixels = new_y2 - new_y1
|
| 189 |
-
box_width_cm = box_width_pixels * conversion_factor
|
| 190 |
-
box_height_cm = box_height_pixels * conversion_factor
|
| 191 |
-
width_str = f"{box_width_cm:.1f}"
|
| 192 |
-
height_str = f"{box_height_cm:.1f}"
|
| 193 |
-
elif conversion_factor is not None:
|
| 194 |
-
# Fallback: use direct pixel measurements
|
| 195 |
box_width_pixels = x2 - x1
|
| 196 |
box_height_pixels = y2 - y1
|
| 197 |
-
box_width_cm = box_width_pixels *
|
| 198 |
-
box_height_cm = box_height_pixels *
|
| 199 |
width_str = f"{box_width_cm:.1f}"
|
| 200 |
height_str = f"{box_height_cm:.1f}"
|
| 201 |
else:
|
|
|
|
| 75 |
return filtered_preds
|
| 76 |
|
| 77 |
#########################################
|
| 78 |
+
# 3. Processing Function with Pose-based Measurement
|
| 79 |
#########################################
|
| 80 |
|
| 81 |
def process_image(job_id, image_path, object_type):
|
|
|
|
| 109 |
for prediction in predictions:
|
| 110 |
try:
|
| 111 |
x, y, width, height = prediction["x"], prediction["y"], prediction["width"], prediction["height"]
|
| 112 |
+
# Convert from center (x, y) and width, height to top-left & bottom-right
|
| 113 |
x1 = int(round(x - width / 2))
|
| 114 |
y1 = int(round(y - height / 2))
|
| 115 |
x2 = int(round(x + width / 2))
|
| 116 |
y2 = int(round(y + height / 2))
|
| 117 |
+
# Clamp coordinates to image boundaries
|
| 118 |
x1 = max(0, min(x1, img_width - 1))
|
| 119 |
y1 = max(0, min(y1, img_height - 1))
|
| 120 |
x2 = max(0, min(x2, img_width - 1))
|
|
|
|
| 128 |
continue
|
| 129 |
|
| 130 |
box_detections = custom_nms(processed_preds, iou_threshold=0.3)
|
| 131 |
+
jobs[job_id]['progress'] = 40
|
| 132 |
|
| 133 |
# -------------------------------
|
| 134 |
+
# Use ArUco pose estimation to compute a conversion factor.
|
| 135 |
+
# IMPORTANT: For accurate measurement you need proper camera calibration.
|
| 136 |
+
# Replace the cameraMatrix and distCoeffs below with your calibrated parameters.
|
| 137 |
+
# Here we use an approximate calibration.
|
| 138 |
# -------------------------------
|
| 139 |
+
marker_conversion_factor = None
|
|
|
|
|
|
|
|
|
|
| 140 |
try:
|
| 141 |
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
| 142 |
aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)
|
|
|
|
| 143 |
if hasattr(cv2.aruco, 'DetectorParameters_create'):
|
| 144 |
aruco_params = cv2.aruco.DetectorParameters_create()
|
| 145 |
else:
|
| 146 |
aruco_params = cv2.aruco.DetectorParameters()
|
| 147 |
corners, ids, _ = cv2.aruco.detectMarkers(gray, aruco_dict, parameters=aruco_params)
|
| 148 |
if ids is not None and len(corners) > 0:
|
| 149 |
+
# Use the first detected marker
|
| 150 |
+
# --- IMPORTANT ---
|
| 151 |
+
# Define your camera calibration parameters below. These are only approximate.
|
| 152 |
+
fx = 1.2 * img_width
|
| 153 |
+
fy = 1.2 * img_height
|
| 154 |
+
cx = img_width / 2
|
| 155 |
+
cy = img_height / 2
|
| 156 |
+
cameraMatrix = np.array([[fx, 0, cx],
|
| 157 |
+
[0, fy, cy],
|
| 158 |
+
[0, 0, 1]], dtype=np.float32)
|
| 159 |
+
distCoeffs = np.zeros((5, 1), dtype=np.float32)
|
| 160 |
+
# Marker length in meters (10 cm = 0.10 m)
|
| 161 |
+
marker_length = 0.10
|
| 162 |
+
rvecs, tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(corners, marker_length, cameraMatrix, distCoeffs)
|
| 163 |
+
# For the first marker:
|
| 164 |
+
rvec = rvecs[0]
|
| 165 |
+
tvec = tvecs[0]
|
| 166 |
+
# Define 3D coordinates for the marker's corners (in marker coordinate system)
|
| 167 |
+
obj_points = np.array([
|
| 168 |
+
[-marker_length/2, marker_length/2, 0],
|
| 169 |
+
[ marker_length/2, marker_length/2, 0],
|
| 170 |
+
[ marker_length/2, -marker_length/2, 0],
|
| 171 |
+
[-marker_length/2, -marker_length/2, 0]
|
| 172 |
+
], dtype=np.float32)
|
| 173 |
+
projected_points, _ = cv2.projectPoints(obj_points, rvec, tvec, cameraMatrix, distCoeffs)
|
| 174 |
+
projected_points = projected_points.reshape((4,2))
|
| 175 |
+
# Compute the pixel distance between two adjacent projected corners (e.g. top edge)
|
| 176 |
+
pixel_distance = np.linalg.norm(projected_points[0] - projected_points[1])
|
| 177 |
+
# Since the marker is 10 cm wide, the conversion factor is:
|
| 178 |
+
marker_conversion_factor = 10.0 / pixel_distance # cm per pixel
|
| 179 |
+
# Optionally, draw the marker pose for visualization:
|
| 180 |
+
cv2.aruco.drawAxis(image, cameraMatrix, distCoeffs, rvec, tvec, 0.05)
|
| 181 |
else:
|
| 182 |
+
marker_conversion_factor = None
|
|
|
|
| 183 |
except Exception as e:
|
| 184 |
+
marker_conversion_factor = None
|
| 185 |
+
|
| 186 |
+
jobs[job_id]['progress'] = 60
|
| 187 |
|
| 188 |
+
# Process each detected box using the conversion factor from pose estimation.
|
| 189 |
for pred in box_detections:
|
| 190 |
x1, y1, x2, y2 = pred["box"]
|
| 191 |
label = pred["class"]
|
| 192 |
confidence = pred["confidence"]
|
| 193 |
cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
|
| 194 |
+
if marker_conversion_factor is not None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 195 |
box_width_pixels = x2 - x1
|
| 196 |
box_height_pixels = y2 - y1
|
| 197 |
+
box_width_cm = box_width_pixels * marker_conversion_factor
|
| 198 |
+
box_height_cm = box_height_pixels * marker_conversion_factor
|
| 199 |
width_str = f"{box_width_cm:.1f}"
|
| 200 |
height_str = f"{box_height_cm:.1f}"
|
| 201 |
else:
|