File size: 3,203 Bytes
7713426
 
6ed7da3
7713426
435517a
6ed7da3
 
7713426
6ed7da3
 
7713426
6ed7da3
 
 
 
 
 
 
4f6565b
6ed7da3
 
 
 
7713426
 
435517a
6ed7da3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
435517a
6ed7da3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7713426
 
6ed7da3
7713426
6ed7da3
7713426
 
6ed7da3
7713426
6ed7da3
 
 
7713426
 
 
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
import gradio as gr
import torch
from ultralytics import YOLO
from PIL import Image
import numpy as np
import easyocr
import cv2

# Load YOLOv8 Model (Nano for speed)
model = YOLO('yolov8n.pt') 

# Load EasyOCR (English)
# This will download the OCR models on first run
reader = easyocr.Reader(['en'], gpu=torch.cuda.is_available())

def detect_and_read(image, threshold):
    # 1. YOLO Detection
    results = model.predict(source=image, conf=threshold)
    
    # 2. EasyOCR Full Page Read
    # Convert PIL to numpy for EasyOCR
    img_np = np.array(image)
    ocr_results = reader.readtext(img_np)
    
    detections = []
    
    # Process YOLO boxes (UI Components)
    for r in results:
        for box in r.boxes:
            b = box.xyxy[0].cpu().numpy() 
            c = box.cls.cpu().item()
            label = model.names[int(c)]
            
            # Box coords [xmin, ymin, xmax, ymax]
            xmin, ymin, xmax, ymax = b
            
            # Link OCR text to this specific YOLO box
            box_text = ""
            for (ocr_box, text, prob) in ocr_results:
                # Calculate OCR center
                ox = (ocr_box[0][0] + ocr_box[2][0]) / 2
                oy = (ocr_box[0][1] + ocr_box[2][1]) / 2
                
                # If text is inside the UI box
                if xmin <= ox <= xmax and ymin <= oy <= ymax:
                    box_text += text + " "
            
            # Normalize coordinates for RapnssZ
            norm_box = [
                float(ymin / image.height), # ymin
                float(xmin / image.width),  # xmin
                float(ymax / image.height), # ymax
                float(xmax / image.width)   # xmax
            ]
            
            detections.append({
                "box": norm_box,
                "label": label,
                "text": box_text.strip(),
                "score": float(box.conf.cpu().item())
            })
            
    # 3. Handle Floating Text (OCR text not inside a YOLO box)
    for (ocr_box, text, prob) in ocr_results:
        already_matched = False
        for d in detections:
            if text in d["text"]:
                already_matched = True
                break
        
        if not already_matched:
            # Add as a 'text' element
            # EasyOCR box format: [[x,y], [x,y], [x,y], [x,y]]
            norm_box = [
                float(ocr_box[0][1] / image.height),
                float(ocr_box[0][0] / image.width),
                float(ocr_box[2][1] / image.height),
                float(ocr_box[2][0] / image.width)
            ]
            detections.append({
                "box": norm_box,
                "label": "text",
                "text": text,
                "score": float(prob)
            })

    return detections

# Gradio Interface
iface = gr.Interface(
    fn=detect_and_read,
    inputs=[
        gr.Image(type="pil", label="Screen Capture"),
        gr.Slider(0, 1, value=0.2, label="Radar Sensitivity (Threshold)")
    ],
    outputs=gr.JSON(label="OCR-Radar Analysis"),
    title="RapnssZ OCR-Radar // Mega v4.5",
    description="Zero-latency UI mapping using YOLOv8 and EasyOCR."
)

iface.launch()