File size: 4,687 Bytes
e9aa8e9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# --- 1. Import all the necessary tools ---
import gradio as gr
import numpy as np
import cv2
import roboflow
import os

# --- 2. Load BOTH of your AI models from Roboflow ---
print("Downloading and loading models from Roboflow...")

# --- ⚙️ PASTE YOUR ROBOFLOW INFORMATION HERE ⚙️ ---
ROBOFLOW_API_KEY = "YfKCsreNkoXYFD1CfMBY"

# --- Model 1: The Plate Detector ---
PLATE_DETECTOR_WORKSPACE_ID = "mylprproject"
PLATE_DETECTOR_PROJECT_ID = "license-plate-yuw1z-kirke"
PLATE_DETECTOR_VERSION = 1 # The version number of your plate detector

# --- Model 2: The Character Reader (Your Specialist!) ---
CHARACTER_READER_WORKSPACE_ID = "mylprproject"
CHARACTER_READER_PROJECT_ID = "pr-character-reader-nqwhr"
CHARACTER_READER_VERSION = 1 # The version number of your character reader

# Authenticate and load models
rf = roboflow.Roboflow(api_key=ROBOFLOW_API_KEY)

project_plate = rf.workspace(PLATE_DETECTOR_WORKSPACE_ID).project(PLATE_DETECTOR_PROJECT_ID)
plate_model = project_plate.version(PLATE_DETECTOR_VERSION).model
print("✅ Plate Detector loaded.")

project_char = rf.workspace(CHARACTER_READER_WORKSPACE_ID).project(CHARACTER_READER_PROJECT_ID)
character_model = project_char.version(CHARACTER_READER_VERSION).model
print("✅ Character Reader loaded.")


# --- 3. Define the main prediction function ---
def detect_license_plate_and_chars(input_image):
    """
    This function uses the full Roboflow two-stage pipeline.
    """
    print("New image received. Starting full pipeline...")
    output_image = input_image.copy()

    # --- STAGE 1: Find the license plate ---
    plate_predictions = plate_model.predict(input_image, confidence=40).json()['predictions']

    if not plate_predictions:
        return output_image, "No license plate found."

    plate_box = plate_predictions[0]
    x1, y1, x2, y2 = [int(plate_box['x'] - plate_box['width'] / 2), int(plate_box['y'] - plate_box['height'] / 2),
                      int(plate_box['x'] + plate_box['width'] / 2), int(plate_box['y'] + plate_box['height'] / 2)]
    
    cv2.rectangle(output_image, (x1, y1), (x2, y2), (0, 0, 255), 2) # Red box for the plate
    plate_crop = input_image[y1:y2, x1:x2]

    # --- STAGE 2: Find and Classify Characters within the plate ---
    # Convert to grayscale and apply a threshold to make characters stand out
    gray_plate = cv2.cvtColor(plate_crop, cv2.COLOR_BGR2GRAY)
    _, thresh_plate = cv2.threshold(gray_plate, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
    
    # Find contours of potential characters
    contours, _ = cv2.findContours(thresh_plate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    detections = []
    for contour in contours:
        x_char, y_char, w_char, h_char = cv2.boundingRect(contour)
        
        # Filter out noise based on size
        if h_char > (plate_crop.shape[0] * 0.3) and w_char > 5:
            # Crop out the character
            char_image = plate_crop[y_char:y_char+h_char, x_char:x_char+w_char]
            
            # --- STAGE 3: Classify the character using your specialist model ---
            char_prediction = character_model.predict(char_image).json()
            
            # Get the top prediction
            top_class = char_prediction['top']
            confidence = char_prediction['confidence']

            if confidence > 0.5: # Only accept confident predictions
                detections.append((x_char, top_class))
                
                # Draw box and label on the main image
                abs_x1, abs_y1 = x1 + x_char, y1 + y_char
                cv2.rectangle(output_image, (abs_x1, abs_y1), (abs_x1 + w_char, abs_y1 + h_char), (0, 255, 0), 1)
                cv2.putText(output_image, top_class, (abs_x1, abs_y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)

    detections.sort(key=lambda x: x[0])
    final_text = "".join([char for _, char in detections])
    
    print(f"Prediction complete. Detected text: {final_text}")
    return output_image, final_text


# --- 4. Create the Gradio Web Interface ---
with gr.Blocks() as demo:
    gr.Markdown("# My Custom LPR System")
    gr.Markdown("This system uses my own two Roboflow models to find the plate and read the characters.")
    
    with gr.Row():
        image_input = gr.Image(type="numpy", label="Upload License Plate Image")
        image_output = gr.Image(type="numpy", label="Result")
    
    text_output = gr.Textbox(label="Detected Characters")
    predict_button = gr.Button(value="Detect Plate and Characters")
    
    predict_button.click(fn=detect_license_plate_and_chars, inputs=image_input, outputs=[image_output, text_output])

# --- 5. Launch the application ---
demo.launch()