| |
| import argparse |
| import json |
| import numpy as np |
| import cv2 |
|
|
| from identify_queue_start_end import identify_start_end_bboxes, load_fpx_from_txt |
|
|
|
|
| def _bbox_edge_flags(bbox_xyxy, W, H, margin_px): |
| x1, y1, x2, y2 = [float(v) for v in bbox_xyxy.tolist()] |
| near_left = x1 <= margin_px |
| near_right = x2 >= (W - 1 - margin_px) |
| near_top = y1 <= margin_px |
| near_bottom = y2 >= (H - 1 - margin_px) |
| touches_any = near_left or near_right or near_top or near_bottom |
| return touches_any, near_left, near_right, near_top, near_bottom |
|
|
|
|
| def _location_bucket_from_center_x(cx, W): |
| |
| r = cx / max(W, 1) |
| if r < 0.2: |
| return "far left" |
| elif r < 0.4: |
| return "center left" |
| elif r < 0.6: |
| return "center" |
| elif r < 0.8: |
| return "center right" |
| else: |
| return "far right" |
|
|
|
|
| def endpoint_fields(bbox_xyxy, W, H, margin_px): |
| """ |
| Returns the 3 fields for one endpoint: |
| visible? location if visible; direction_to_turn if not visible |
| """ |
| x1, y1, x2, y2 = [float(v) for v in bbox_xyxy.tolist()] |
| cx = 0.5 * (x1 + x2) |
|
|
| touches_any, near_left, near_right, near_top, near_bottom = _bbox_edge_flags( |
| bbox_xyxy, W, H, margin_px |
| ) |
|
|
| if touches_any: |
| visible = "no" |
| location = "N/A" |
|
|
| |
| |
| if near_left: |
| turn = "left" |
| else: |
| turn = "right" |
| else: |
| visible = "yes" |
| location = _location_bucket_from_center_x(cx, W) |
| turn = "N/A" |
|
|
| return visible, location, turn |
|
|
|
|
| def main(): |
| ap = argparse.ArgumentParser() |
| ap.add_argument("--image_id", required=True) |
| ap.add_argument("--root", default="/scratch/ds5725/linefinder/LineFinder") |
| ap.add_argument("--margin_px", type=int, default=10, |
| help="Pixels to consider 'close to edge' (default 10)") |
| ap.add_argument("--out_json", default=None, help="Optional output json path") |
| args = ap.parse_args() |
|
|
| image_id = args.image_id |
| root = args.root |
|
|
| image_path = f"{root}/Images/ImagesOnline/{image_id}.JPG" |
| depth_path = f"{root}/depth_map/{image_id}.npy" |
| bbox_path = f"{root}/bbox_orient/{image_id}_bboxes.npy" |
| orient_path = f"{root}/bbox_orient/{image_id}_orient.npy" |
| fpx_path = f"{root}/focal_length_px.txt" |
|
|
| f_px = load_fpx_from_txt(fpx_path, image_id) |
|
|
| |
| res = identify_start_end_bboxes( |
| image_path=image_path, |
| depth_npy_path=depth_path, |
| bboxes_npy_path=bbox_path, |
| orient_npy_path=orient_path, |
| f_px=f_px, |
| ) |
| start_bbox = res["start_bbox_xyxy"] |
| end_bbox = res["end_bbox_xyxy"] |
|
|
| img = cv2.imread(image_path) |
| if img is None: |
| raise FileNotFoundError(f"Could not read image: {image_path}") |
| H, W = img.shape[:2] |
|
|
| |
| end_visible, end_loc, end_turn = endpoint_fields(end_bbox, W, H, args.margin_px) |
|
|
| |
| start_visible, start_loc, start_turn = endpoint_fields(start_bbox, W, H, args.margin_px) |
|
|
| out = { |
| "end_of_line_visible": end_visible, |
| "end_of_line_location_if_visible": end_loc, |
| "direction_to_turn_to_see_end_if_not_visible": end_turn, |
|
|
| "start_of_line_visible": start_visible, |
| "start_of_line_location_if_visible": start_loc, |
| "direction_to_turn_to_see_start_if_not_visible": start_turn, |
| } |
|
|
| print(json.dumps(out, indent=2)) |
|
|
| if args.out_json: |
| with open(args.out_json, "w") as f: |
| json.dump(out, f, indent=2) |
| print(f"Saved: {args.out_json}") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|