Spaces:
Sleeping
Sleeping
File size: 12,554 Bytes
70ebc90 | 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 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | import os
import cv2
import numpy as np
from utils.capture import capture_image
from utils.reference import detect_reference
from utils.detect_objects import run_modelA
from utils.generate_masks import run_modelB
from measure import measure_tool # π₯ connect Model C
from utils.match_spec import run_spec_match # π₯ connect Model D
from utils.visualize_all import visualize_detections
from pathlib import Path
# Get project root (parent of src directory)
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Helper function to get absolute paths
def get_path(relative_path):
return os.path.join(PROJECT_ROOT, relative_path)
def main():
print("π Starting main program...")
# Clean results/measurements and results/predictions for a fresh run
import shutil
for folder in [get_path("outputs/5_measured"), get_path("outputs/6_results")]:
if os.path.exists(folder):
shutil.rmtree(folder)
Path(get_path("outputs/2_reference")).mkdir(parents=True, exist_ok=True)
Path(get_path("outputs/3_detection")).mkdir(parents=True, exist_ok=True)
Path(get_path("outputs/3_detection/labels")).mkdir(parents=True, exist_ok=True)
Path(get_path("outputs/4_segmentation/masks")).mkdir(parents=True, exist_ok=True)
Path(get_path("outputs/4_segmentation/overlay")).mkdir(parents=True, exist_ok=True)
Path(get_path("outputs/5_measured")).mkdir(parents=True, exist_ok=True)
Path(get_path("outputs/6_results/spec_match_report")).mkdir(parents=True, exist_ok=True)
Path(get_path("outputs/6_results/output_images")).mkdir(parents=True, exist_ok=True)
# Step 1: Capture image
status, img_path = capture_image()
if status != "success":
print("β οΈ No image saved. Exiting program.")
return
# Step 2: Detect reference square
ref_status, px_per_mm, ref_points = detect_reference(
image_path=img_path,
ref_size_mm=20.0, # standard reference square size in mm
save_path=get_path("outputs/2_reference") # folder to save annotated reference image
)
if ref_status == "success":
print(f"β
Reference detected. Pixels per mm: {px_per_mm:.2f}")
else:
print("β Reference not detected. Check image quality or lighting.")
px_per_mm = None
# Step 3: Run Model A (Object Detection)
print("π― Running Model A for object detection...")
detections, label_path = run_modelA(
image_path=img_path,
model_path=get_path("models/model_a.pt"),
device="cpu", # change to "0" for GPU
imgsz=640,
conf_thr=0.25,
iou_thr=0.5,
save_annotated=True,
outdir=get_path("outputs/3_detection"),
save_labels=True
)
if detections:
print("\nβ
Detected objects:")
for i, det in enumerate(detections):
print(f"{i+1}. {det['class_name']}")
print()
else:
print("β οΈ No objects detected.")
# Step 4: Run Model B (Segmentation/Mask Generation)
mask_array = None
if label_path and detections:
print("π― Running Model B for segmentation/mask generation...")
result = run_modelB(
img_path=img_path,
label_txt_path=label_path
)
if result and "mask_array" in result:
mask_array = result["mask_array"]
print("β
Mask generated and saved successfully.")
print()
else:
print("β οΈ No masks generated.")
else:
print("β οΈ Skipping Model B (no labels from Model A).")
# Step 5: Run Model C (Measurements)
measurement_results = {}
if detections:
print("π Running Model C (Measurements)...")
measurement_results = measure_tool.process_measurements(
image_path=img_path,
detections=detections,
label_path=label_path,
mask_data=mask_array,
px_per_mm=px_per_mm
)
if measurement_results:
for obj_id, res in measurement_results.items():
class_name = res.get('class', 'unknown')
if class_name == 'washer':
print("β
Washer measurement saved.")
elif class_name == 'bolt':
print("β
Bolt measurement saved.")
elif class_name == 'nut':
print("β
Nut measurement saved.")
elif class_name == 'screw':
print("β
Screw measurement saved.")
else:
print("β οΈ No valid measurements returned.")
else:
print("β οΈ Skipping Model C (no detections).")
# Step 6: Run Model D (Specification Matching)
spec_results = []
if measurement_results:
print("π Running Model D (Specification Matching)...")
report_path = get_path("outputs/6_results/spec_match_report/spec_match_report.txt")
reference_csv_dict = {
"washer": get_path("data/datasets/washers_dataset.csv"),
"bolt": get_path("data/datasets/bolts_dataset.csv"),
"nut": get_path("data/datasets/nuts_dataset.csv"),
"screw": get_path("data/datasets/screws_dataset.csv")
}
spec_results = run_spec_match(
measurements_dir=get_path("outputs/5_measured"),
reference_csv_dict=reference_csv_dict,
output_txt=report_path
)
print(f"β
Spec matching completed. Report saved at: {report_path}")
else:
print("β οΈ Skipping Model D (no measurements to match).")
# --- Visualization: overlay bbox, mask, predicted dims ---
if detections:
image = cv2.imread(img_path)
det_list = []
mask_list = []
meas_list = []
# Create a mapping of object_id to predicted values
predicted_values = {}
for spec_res in spec_results:
if spec_res['reference']:
file_name = Path(spec_res['file']).stem
obj_id = file_name.replace('_measured', '')
predicted_values[obj_id] = spec_res['reference']
# Process all detections for visualization
for idx, det in enumerate(detections):
cls_name = det['class_name'].lower()
bbox = det['xyxy']
det_list.append({'label': det['class_name'], 'bbox': bbox})
# Find corresponding measurement result
obj_id = f"{cls_name}_{idx+1}"
meas = measurement_results.get(obj_id, {})
# Extract mask from Model B
if mask_array is not None:
x1, y1, x2, y2 = map(int, bbox)
if isinstance(mask_array, (list, tuple)) and idx < len(mask_array):
obj_mask = np.zeros(image.shape[:2], dtype=np.uint8)
mask_obj = mask_array[idx]
if mask_obj.shape != obj_mask.shape:
mask_obj = cv2.resize(mask_obj, (obj_mask.shape[1], obj_mask.shape[0]), interpolation=cv2.INTER_NEAREST)
obj_mask = (mask_obj > 0).astype(np.uint8)
mask_list.append(obj_mask)
elif isinstance(mask_array, np.ndarray) and mask_array.ndim == 3 and idx < mask_array.shape[0]:
mask_obj = mask_array[idx]
obj_mask = (mask_obj > 0).astype(np.uint8)
mask_list.append(obj_mask)
elif isinstance(mask_array, np.ndarray) and mask_array.ndim == 2:
obj_mask = np.zeros(image.shape[:2], dtype=np.uint8)
mask_crop = mask_array[y1:y2, x1:x2]
obj_mask[y1:y2, x1:x2] = (mask_crop > 0).astype(np.uint8)
mask_list.append(obj_mask)
else:
mask_list.append(np.zeros(image.shape[:2], dtype=np.uint8))
else:
mask_list.append(np.zeros(image.shape[:2], dtype=np.uint8))
# Use predicted values if available, otherwise fall back to measured values
pred_vals = predicted_values.get(obj_id, {})
dims = {}
if meas.get('class') == 'bolt' and pred_vals:
if 'Bolt Size' in pred_vals:
dims['Nominal_M'] = pred_vals['Bolt Size']
if 'Length_mm' in pred_vals and pred_vals['Length_mm'] is not None:
dims['Length_mm'] = float(pred_vals['Length_mm'])
elif meas.get('class') == 'washer' and pred_vals:
if 'OD_mm' in pred_vals and pred_vals['OD_mm'] is not None:
dims['OD'] = float(pred_vals['OD_mm'])
if 'ID_mm' in pred_vals and pred_vals['ID_mm'] is not None:
dims['ID'] = float(pred_vals['ID_mm'])
elif meas.get('class') == 'nut' and pred_vals:
if 'Nominal Dia' in pred_vals:
dims['Nominal_Dia'] = pred_vals['Nominal Dia']
if 'AF_mm' in pred_vals and pred_vals['AF_mm'] is not None:
dims['AF'] = float(pred_vals['AF_mm'])
elif meas.get('class') == 'screw' and pred_vals:
if 'Length_mm' in pred_vals and pred_vals['Length_mm'] is not None:
dims['Length_mm'] = float(pred_vals['Length_mm'])
if 'Nominal Dia' in pred_vals:
dims['Nominal_Dia'] = pred_vals['Nominal Dia']
else:
if meas.get('OD_mm') is not None:
dims['OD'] = float(meas['OD_mm'])
if meas.get('ID_mm') is not None:
dims['ID'] = float(meas['ID_mm'])
if meas.get('AF_mm') is not None:
dims['AF'] = float(meas['AF_mm'])
if meas.get('Length_mm') is not None:
dims['Length_mm'] = float(meas['Length_mm'])
if meas.get('class') == 'screw' and 'Length_mm' in meas and 'Length_mm' not in dims and meas['Length_mm'] is not None:
dims['Length_mm'] = float(meas['Length_mm'])
meas_list.append(dims)
# Visualize all detections
if det_list:
result_img = visualize_detections(image, det_list, mask_list, meas_list)
out_img_path = get_path("outputs/6_results/output_images/final_output.jpg")
cv2.imwrite(out_img_path, result_img)
print("\nπΌοΈ Displaying final output image...")
cv2.imshow("Final Detection & Measurement Results", result_img)
print("Press any key to close the image window...")
cv2.waitKey(0)
cv2.destroyAllWindows()
print("\nπ PROCESSING SUMMARY:")
print(f" Components with measurements: {len(measurement_results)}")
for obj_id, meas in measurement_results.items():
print(f"\n π§ {obj_id.upper()}:")
print(f" Class: {meas['class']}")
if meas['class'] == 'bolt':
pred = predicted_values.get(obj_id, {})
print(f" β€ Bolt Size: {pred.get('Bolt Size', 'N/A')}")
print(f" β€ AF (Across Flats): {pred.get('AF_mm', 'N/A')} mm")
print(f" β€ Length: {pred.get('Length_mm', 'N/A')} mm")
elif meas['class'] == 'washer':
pred = predicted_values.get(obj_id, {})
print(f" β€ Outer Diameter (OD): {pred.get('OD_mm', 'N/A')} mm")
print(f" β€ Inner Diameter (ID): {pred.get('ID_mm', 'N/A')} mm")
elif meas['class'] == 'nut':
pred = predicted_values.get(obj_id, {})
print(f" β€ Nut Size: {pred.get('Nut Size', 'N/A')}")
print(f" β€ Across Flats (AF): {pred.get('AF_mm', 'N/A')} mm")
elif meas['class'] == 'screw':
pred = predicted_values.get(obj_id, {})
print(f" β€ Screw Size: {pred.get('Screw Size', 'N/A')}")
print(f" β€ Length: {pred.get('Length_mm', 'N/A')} mm")
print("\nβ
ANALYSIS COMPLETED...")
print("run again for next components")
if __name__ == "__main__":
main()
|