Thai ID Nano OCR — Card Field Detector (YOLO26n)
4-class text zone detector for Thai National ID cards. Detects field regions
on raw camera frames and routes each crop to the appropriate OCR Reader expert.
Trained with driver license negative mining to suppress false detections on non-ID documents.
Designed for on-device inference at 30fps on mobile.
Metrics
Metric Value Architecture YOLO26n Task detect Classes 4 mAP50 0.986 mAP50-95 0.927 Precision 0.948 Recall 0.958 Parameters ~2.5M GFLOPs 5.8 (fused) Input 640x640 Experiment EXP-015
Training Data
Synth (850) + real (138) + deduped v10i (165) + DL neg (45) + CPFGS neg (200) = 1398 train / 206 val
Mixed synthetic and real images. Synthetic cards rendered with augmentations
(perspective warp, brightness/contrast, noise, blur, JPEG compression) on
random backgrounds. Real images from Roboflow with manual 4-class annotations.
Driver license images included as background negatives (empty labels) to suppress
false field detections on non-ID-card documents.
Negative Mining Results
Metric v1 (no neg) v2 (45 DL neg) v3 (245 neg) DL False Positive Rate 97.8% 2.2% 0.0% Phantom Detections (45 DL images) 739 1 0 Max FP Confidence 0.901 0.336 0.000
Sample Results
Confusion Matrix (Normalized)
Confusion Matrix
Precision-Recall Curve
PR Curve
Training Curves
Training Results
F1-Confidence Curve
F1 Curve
Label Distribution
Labels
Quick Start
1 from huggingface_hub import hf_hub_download
2 from ultralytics import YOLO
3
4 model_path = hf_hub_download ( "chayuto/thai-id-ocr-yolo26n-card-field-detector" , "best.pt" )
5 model = YOLO ( model_path )
6 results = model ( "path/to/id_card_photo.jpg" )
7
8 for box in results [ 0 ] . boxes :
9 cls_id = int ( box . cls )
10 conf = float ( box . conf )
11 x1 , y1 , x2 , y2 = box . xyxy [ 0 ] . tolist ( )
12 print ( f"Class { cls_id } ( { conf : .2f } ): [ { x1 : .0f } , { y1 : .0f } , { x2 : .0f } , { y2 : .0f } ]" )
Classes
ID Name Routes to 0 num_id_zoneNumeric OCR Expert (13-digit CID) 1 num_dob_zoneNumeric OCR Expert (DD/MM/YYYY Buddhist Era) 2 text_eng_zoneEnglish OCR Expert (romanized Thai names) 3 text_thai_zoneThai OCR Expert (names, addresses, dates, religion)
Fields are grouped by OCR engine type (3 experts), not semantic meaning (10+ fields).
Card boundary detection is handled separately by Pipeline B (YOLO26n-Pose with 4-corner keypoints).
Architecture
YOLO26n — NMS-free, DFL-free single-pass detector.
Input: [1, 3, 640, 640]
→ YOLO26n backbone + neck
→ 4-class bbox detection head
Output: [1, 300, 8] (NMS-free, top-300 detections)
→ [x1, y1, x2, y2, conf, class_0, class_1, class_2, class_3]
Pipeline Context
This model is the Finder stage of the Thai ID Nano OCR pipeline:
Camera Frame (640x640)
→ YOLO26n Finder (this model) — 4-class text zone detection
→ num_id_zone, num_dob_zone → Numeric Reader (~98.6% EM)
→ text_eng_zone → English Reader (~97.6% EM)
→ text_thai_zone → Thai Reader (~95.3% EM)
→ YOLO26n-Pose (Pipeline B) — card boundary + 4-corner keypoints
→ Validator (CID Mod11 checksum, date logic)
Total pipeline: <15 MB, 30fps on mobile.
TFLite Export
1 from ultralytics import YOLO
2 model = YOLO ( "best.pt" )
3 model . export ( format = "tflite" , int8 = True , nms = False , imgsz = 640 )
Files
File Description best.ptUltralytics YOLO26n weights (~5.1 MB) config.jsonArchitecture params, training metadata, per-class metrics confusion_matrix_normalized.pngNormalized confusion matrix BoxPR_curve.pngPrecision-Recall curve (all classes) BoxF1_curve.pngF1-Confidence curve results.pngTraining loss and metric curves labels.jpgDataset label distribution and bbox statistics
License
MIT