import cv2 import base64 import csv import numpy as np from pathlib import Path from typing import List, Dict, Any def draw_boxes(image: np.ndarray, detections: List[Dict[str, Any]]) -> np.ndarray: """ Draws bounding boxes and confidence labels on an image array based on detections. Inputs: image: A numpy array representing the image (BGR format). detections: A list of dictionaries, each containing 'xyxy' (list of [x1, y1, x2, y2]), 'confidence' (float), and 'class_id' (int). Outputs: A copy of the input numpy array with bounding boxes plotted. Side effects: Does not mutate the original image array; returns a new annotated copy. """ img_copy = image.copy() for det in detections: # Convert bounding box coordinates to integers since cv2 expects integer pixels x1, y1, x2, y2 = map(int, det['xyxy']) conf = det['confidence'] # Pothole label construction label = f"Pothole: {conf:.2f}" # Draw the rectangle cv2.rectangle(img_copy, (x1, y1), (x2, y2), (0, 0, 255), 2) # Place the text above the bounding box cv2.putText(img_copy, label, (x1, max(y1 - 10, 10)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2) return img_copy def image_to_base64(image: np.ndarray) -> str: """ Converts a numpy image array to a base64 encoded string. Inputs: image: A numpy array representing the image. Outputs: A base64 encoded string of the compressed PNG version of the image. Side effects: None. """ success, buffer = cv2.imencode('.png', image) if not success: return "" b64_str = base64.b64encode(buffer).decode('utf-8') return b64_str def export_csv(detections: List[Dict[str, Any]], export_path: str | Path) -> None: """ Writes a list of detection dictionaries to a CSV file. Inputs: detections: A list of detection dictionaries containing flattened key-value pairs (e.g., filename, confidence, latitude, etc.). export_path: The file path (string or pathlib.Path) where the CSV will be saved. Outputs: None. Side effects: Creates or overwrites a file at the specified absolute export_path. Creates parent directories iteratively if they do not exist. """ file_path = Path(export_path) # Ensure immediate directory exists file_path.parent.mkdir(parents=True, exist_ok=True) if not detections: file_path.touch() return # Extract dynamic keys efficiently keys = list(detections[0].keys()) with file_path.open('w', newline='', encoding='utf-8') as f: dict_writer = csv.DictWriter(f, fieldnames=keys) dict_writer.writeheader() dict_writer.writerows(detections)