PlatDetect / backend /app /ocr_engine.py
haisyam's picture
Update kodingan PlatDetect
1f6c75f
Raw History Blame Contribute Delete
5.24 kB
"""
ocr_engine.py β€” Multi-preprocessing OCR engine menggunakan EasyOCR.
Menjalankan OCR pada beberapa versi preprocessing dan memilih hasil terbaik.
"""
import cv2
import numpy as np
from app.plate_formatter import clean_text, format_plate_candidate, score_plate_text
# ── Singleton EasyOCR Reader ────────────────────────────────────────────────
_reader = None
def load_reader():
"""Load EasyOCR reader sekali saja (singleton). GPU=False untuk CPU basic."""
global _reader
if _reader is None:
import easyocr
_reader = easyocr.Reader(['en'], gpu=False)
return _reader
# ── Preprocessing Functions ─────────────────────────────────────────────────
def crop_main_plate_line(plate_crop):
"""
Ambil bagian atas plat saja (sekitar 58% tinggi crop).
Ini untuk menghindari terbacanya masa berlaku (misal '05 26')
yang ada di baris bawah plat Indonesia.
"""
if plate_crop is None or plate_crop.size == 0:
return plate_crop
h, w = plate_crop.shape[:2]
main_line = plate_crop[0:int(h * 0.58), 0:w]
# Pastikan crop tidak terlalu kecil
if main_line.shape[0] < 10 or main_line.shape[1] < 10:
return plate_crop
return main_line
def make_ocr_versions(plate_crop) -> dict:
"""
Membuat beberapa versi preprocessing dari crop plat untuk OCR.
Setiap versi mengoptimalkan aspek berbeda dari gambar plat.
Versi yang dihasilkan:
- gray: Grayscale standar
- clahe: Contrast-Limited Adaptive Histogram Equalization
- blur: Gaussian blur untuk mengurangi noise
- sharp: Sharpening untuk memperjelas tepi karakter
- otsu: Otsu thresholding untuk binarisasi
- inverted: Versi terbalik dari otsu
"""
versions = {}
# Konversi ke grayscale jika belum
if len(plate_crop.shape) == 3:
gray = cv2.cvtColor(plate_crop, cv2.COLOR_BGR2GRAY)
else:
gray = plate_crop.copy()
# 1. Gray β€” baseline
versions["gray"] = gray
# 2. CLAHE β€” adaptive contrast enhancement
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
versions["clahe"] = clahe.apply(gray)
# 3. Blur β€” gaussian blur untuk kurangi noise
versions["blur"] = cv2.GaussianBlur(gray, (3, 3), 0)
# 4. Sharp β€” kernel sharpening
kernel_sharp = np.array([[-1, -1, -1],
[-1, 9, -1],
[-1, -1, -1]])
versions["sharp"] = cv2.filter2D(gray, -1, kernel_sharp)
# 5. Otsu β€” binary thresholding otomatis
blurred_for_otsu = cv2.GaussianBlur(gray, (5, 5), 0)
_, otsu = cv2.threshold(blurred_for_otsu, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
versions["otsu"] = otsu
# 6. Inverted β€” kebalikan dari otsu
versions["inverted"] = cv2.bitwise_not(otsu)
return versions
# ── Multi-OCR Reader ────────────────────────────────────────────────────────
def read_plate_with_multi_ocr(plate_crop) -> dict:
"""
Menjalankan OCR pada semua versi preprocessing dan memilih hasil terbaik
berdasarkan skor format plat Indonesia.
Args:
plate_crop: Gambar crop area plat (numpy array BGR atau grayscale)
Returns:
dict: {
"raw": "H2148BL",
"formatted": "H 2148 BL",
"score": 120,
"version": "clahe"
}
"""
reader = load_reader()
# Ambil baris utama plat (tanpa masa berlaku)
main_crop = crop_main_plate_line(plate_crop)
# Buat semua versi preprocessing
versions = make_ocr_versions(main_crop)
best_result = {
"raw": "",
"formatted": "",
"score": 0,
"version": "none",
}
allowlist = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
for version_name, version_img in versions.items():
try:
# Jalankan OCR
results = reader.readtext(
version_img,
allowlist=allowlist,
detail=1,
paragraph=False,
)
# Gabungkan semua teks yang terdeteksi
raw_texts = []
for detection in results:
text = detection[1] if len(detection) > 1 else ""
text = clean_text(text)
if text:
raw_texts.append(text)
combined_raw = "".join(raw_texts)
if not combined_raw:
continue
# Format dan skor
formatted = format_plate_candidate(combined_raw)
score = score_plate_text(combined_raw)
# Update best jika skor lebih tinggi
if score > best_result["score"]:
best_result = {
"raw": combined_raw,
"formatted": formatted,
"score": score,
"version": version_name,
}
except Exception:
continue
return best_result