File size: 4,200 Bytes
66f92c3
 
 
 
 
 
 
 
397a7ab
 
7e9442c
66f92c3
 
 
 
397a7ab
66f92c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
836ce8f
66f92c3
 
 
 
836ce8f
66f92c3
 
 
 
 
 
 
 
 
836ce8f
 
 
 
 
66f92c3
 
 
 
 
 
836ce8f
 
66f92c3
 
836ce8f
 
 
 
 
66f92c3
836ce8f
 
 
 
 
 
 
 
 
66f92c3
836ce8f
30f9caf
bd2caa4
 
836ce8f
 
bd2caa4
836ce8f
 
af2ae00
397a7ab
af2ae00
 
 
 
397a7ab
af2ae00
66f92c3
 
836ce8f
 
66f92c3
e09e5d6
836ce8f
66f92c3
e09e5d6
84a3a84
836ce8f
 
e09e5d6
 
 
7bebe90
 
 
 
e09e5d6
 
66f92c3
397a7ab
84a3a84
397a7ab
e09e5d6
836ce8f
 
66f92c3
 
3042eae
66f92c3
 
836ce8f
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
import gradio as gr
import cv2
import numpy as np
import onnxruntime as ort
import requests
from PIL import Image
import io

# Load logo image with alpha channel (PNG with transparency)
logo = cv2.imread('logo.png', cv2.IMREAD_UNCHANGED)

# 1. Load the ONNX model once (CPU)
session = ort.InferenceSession("license_plate_yolo8.onnx", providers=["CPUExecutionProvider"])
input_name = session.get_inputs()[0].name

# 2. Preprocessing logic
def preprocess(img, size=640):
    h0, w0 = img.shape[:2]
    r = size / max(h0, w0)
    new_w, new_h = int(w0 * r), int(h0 * r)
    resized = cv2.resize(img, (new_w, new_h))
    dw, dh = size - new_w, size - new_h
    dw, dh = dw / 2, dh / 2
    top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
    left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
    padded = cv2.copyMakeBorder(resized, top, bottom, left, right,
                                cv2.BORDER_CONSTANT, value=(114,114,114))
    img_rgb = cv2.cvtColor(padded, cv2.COLOR_BGR2RGB)
    img_norm = img_rgb.astype(np.float32) / 255.0
    img_trans = img_norm.transpose(2,0,1)[None, ...]
    return img_trans, r, (left, top), (h0, w0)

# 3. Postprocessing logic
def postprocess(preds, r, pad, orig_shape, conf_thres=0.25, iou_thres=0.45):
    pad_x, pad_y = pad
    orig_h, orig_w = orig_shape
    raw = preds[0].squeeze(0)
    dets = raw.T  # shape (N,5)

    boxes, scores = [], []
    for x_center, y_center, w, h, conf in dets:
        if conf < conf_thres:
            continue
        xc = (x_center - pad_x) / r
        yc = (y_center - pad_y) / r
        bw = w / r
        bh = h / r
        x1 = max(0, xc - bw/2)
        y1 = max(0, yc - bh/2)
        x2 = min(orig_w, xc + bw/2)
        y2 = min(orig_h, yc + bh/2)
        boxes.append([int(x1), int(y1), int(x2-x1), int(y2-y1)])
        scores.append(float(conf))

    idxs = cv2.dnn.NMSBoxes(boxes, scores, conf_thres, iou_thres)
    if len(idxs) > 0:
        idxs = idxs.flatten()
        boxes = [boxes[i] for i in idxs]
    else:
        boxes = []
    return boxes

# 4. Overlay logo in detected boxes
def overlay_logo(img, boxes):
    if logo is None:
        print("Logo image not found. Please ensure 'logo.png' is in the working directory.")
        return img
    for x, y, w, h in boxes:
        overlay = cv2.resize(logo, (w, h), interpolation=cv2.INTER_AREA)
        if overlay.shape[2] == 4:
            alpha = overlay[:, :, 3] / 255.0
            for c in range(3):
                img[y:y+h, x:x+w, c] = (alpha * overlay[:, :, c] +
                                        (1 - alpha) * img[y:y+h, x:x+w, c])
        else:
            img[y:y+h, x:x+w] = overlay
    return img

# 5. Helper to load image from URL
def load_image_from_url(url):
    resp = requests.get(url)
    img_pil = Image.open(io.BytesIO(resp.content)).convert("RGB")
    img = np.array(img_pil)[..., ::-1]
    return img

# 6. Combined pipeline: detect and overlay logo
def detect_and_overlay(uploaded_image, url):
    if uploaded_image is not None:
        img_bgr = uploaded_image[..., ::-1]
    elif url:
        img_bgr = load_image_from_url(url)
    else:
        return None

    inp, r, pad, orig = preprocess(img_bgr)
    preds = session.run(None, {input_name: inp})
    boxes = postprocess(preds, r, pad, orig)
    out_img = overlay_logo(img_bgr, boxes)
    return out_img[..., ::-1]

# 7. Gradio UI with preloaded examples

def main():
    image_input = gr.Image(type="numpy", label="Upload Image")
    # url_input = gr.Textbox(label="(OR) Image URL")

    # List your preloaded vehicle images here (place files in 'preload_images/' folder)
    examples = [
        ["test/1.jpg", ""],
        ["test/2.jpg", ""],
        ["test/3.jpg", ""],
        ["test/4.jpg", ""],
        ["test/5.jpg", ""],
        ["test/7.jpg", ""],
    ]

    iface = gr.Interface(
        fn=detect_and_overlay,
        inputs=[image_input],
        outputs=gr.Image(type="numpy", label="Output Image"),
        examples=examples,
        title="Fenix - License Plate logo",
        description="Upload a vehicle image or click a thumbnail.",
        allow_flagging="never"
    )
    iface.launch(share=True)

if __name__ == "__main__":
    main()