CoolFace
Apppublic

premdeep09/ANPR-System

sourceHugging Faceupdated 5mo agoView on Hugging Face
0likes
bounding_box_detector.py148 linesDownload Raw Back to root
1import cv22from ultralytics import YOLO3import time4 5class ANPRDetector:6    def __init__(self, mode="two_stage", vehicle_model_path="yolov8n.pt", plate_model_path="best_plate.pt"):7        """8        Initializes the ANPR Bounding Box Detector.9        10        Args:11            mode (str): "single_model" (detects both vehicles and plates) or 12                        "two_stage" (detects vehicles, then crops and detects plates).13            vehicle_model_path (str): Path to YOLOv8 model for vehicles.14            plate_model_path (str): Path to YOLOv8 model for plates (needed for two-stage, or single-model if it handles both).15        """16        self.mode = mode17        18        if self.mode == "single_model":19            # In single model mode, one YOLO model is trained to detect classes: 0: vehicle, 1: license_plate20            print(f"Loading Single Model from {plate_model_path}...")21            self.model = YOLO(plate_model_path)22        else:23            # Two-stage mode: model 1 detects cars, model 2 detects plates within crops24            print(f"Loading Vehicle Model from {vehicle_model_path}...")25            self.vehicle_model = YOLO(vehicle_model_path)26            27            print(f"Loading Plate Model from {plate_model_path}...")28            # Note: For this demo, assuming you have a trained YOLOv8 for plates. 29            # Fallback to YOLOv8n if file doesn't exist, though it won't detect plates without training.30            try:31                self.plate_model = YOLO(plate_model_path)32            except Exception:33                print(f"Warning: {plate_model_path} not found. Using yolov8n.pt as placeholder.")34                self.plate_model = YOLO("yolov8n.pt")35 36        # Standard COCO classes for vehicles (car, motorcycle, bus, truck)37        self.vehicle_classes = [2, 3, 5, 7]38 39    def process_frame(self, frame):40        """41        Processes a single frame, drawing tight bounding boxes and extracting plate crops.42        """43        processed_frame = frame.copy()44        plate_crops = []45 46        if self.mode == "single_model":47            # Single forward pass for both vehicles and plates48            results = self.model(processed_frame, verbose=False)49            50            for r in results:51                for box in r.boxes:52                    cls_id = int(box.cls[0])53                    conf = float(box.conf[0])54                    x1, y1, x2, y2 = map(int, box.xyxy[0])55                    56                    if conf < 0.5:57                        continue58                        59                    # Assuming class 0 is Vehicle and class 1 is Plate60                    if cls_id == 0:61                        # Draw vehicle bounding box62                        cv2.rectangle(processed_frame, (x1, y1), (x2, y2), (255, 0, 0), 2)63                        cv2.putText(processed_frame, f"Vehicle {conf:.2f}", (x1, max(y1 - 10, 0)), 64                                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)65                    elif cls_id == 1:66                        # Draw plate bounding box67                        cv2.rectangle(processed_frame, (x1, y1), (x2, y2), (0, 255, 255), 2)68                        cv2.putText(processed_frame, f"Plate {conf:.2f}", (x1, max(y1 - 10, 0)), 69                                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 2)70                                    71                        # Crop the plate region72                        plate_crop = frame[y1:y2, x1:x2]73                        if plate_crop.size > 0:74                            plate_crops.append(plate_crop)75 76        elif self.mode == "two_stage":77            # Stage 1: Detect Vehicles78            vehicle_results = self.vehicle_model(processed_frame, classes=self.vehicle_classes, verbose=False)79            80            for r in vehicle_results:81                for box in r.boxes:82                    conf = float(box.conf[0])83                    if conf < 0.5:84                        continue85                        86                    v_x1, v_y1, v_x2, v_y2 = map(int, box.xyxy[0])87                    88                    # Draw vehicle bounding box89                    cv2.rectangle(processed_frame, (v_x1, v_y1), (v_x2, v_y2), (255, 0, 0), 2)90                    cv2.putText(processed_frame, f"Vehicle {conf:.2f}", (v_x1, max(v_y1 - 10, 0)), 91                                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)92                    93                    vehicle_crop = frame[v_y1:v_y2, v_x1:v_x2]94                    if vehicle_crop.size == 0:95                        continue96                        97                    # Stage 2: Detect Plate inside the Vehicle Crop98                    plate_results = self.plate_model(vehicle_crop, verbose=False)99                    100                    for pr in plate_results:101                        for p_box in pr.boxes:102                            p_conf = float(p_box.conf[0])103                            if p_conf < 0.5:104                                continue105                                106                            # Coordinates relative to the crop107                            px1, py1, px2, py2 = map(int, p_box.xyxy[0])108                            109                            # Convert to absolute coordinates110                            abs_x1 = v_x1 + px1111                            abs_y1 = v_y1 + py1112                            abs_x2 = v_x1 + px2113                            abs_y2 = v_y1 + py2114                            115                            # Draw plate bounding box116                            cv2.rectangle(processed_frame, (abs_x1, abs_y1), (abs_x2, abs_y2), (0, 255, 255), 2)117                            cv2.putText(processed_frame, f"Plate {p_conf:.2f}", (abs_x1, max(abs_y1 - 10, 0)), 118                                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 2)119                                        120                            # Extract tight crop121                            plate_crop = frame[abs_y1:abs_y2, abs_x1:abs_x2]122                            if plate_crop.size > 0:123                                plate_crops.append(plate_crop)124 125        return processed_frame, plate_crops126 127if __name__ == "__main__":128    # Choose your approach here: "single_model" or "two_stage"129    detector = ANPRDetector(mode="two_stage")130    131    # Optional testing logic132    # cap = cv2.VideoCapture(0)133    # while True:134    #     ret, frame = cap.read()135    #     if not ret: break136        137    #     start_time = time.time()138    #     output_frame, crops = detector.process_frame(frame)139    #     fps = 1.0 / (time.time() - start_time)140        141    #     cv2.putText(output_frame, f"FPS: {fps:.2f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)142    #     cv2.imshow("Detection Bounding Boxes", output_frame)143        144    #     if cv2.waitKey(1) & 0xFF == ord('q'):145    #         break146    # cap.release()147    # cv2.destroyAllWindows()148