PCB AOI · YOLO26 electronic component detector (RMUTT)
YOLO26 models that find 11 kinds of electronic components on printed circuit boards. They are the vision part of a PCB automated optical inspection (AOI) machine built at Rajamangala University of Technology Thanyaburi (RMUTT): a 4K camera on an XY gantry visits every point of a board, the model detects the parts in each frame, and the machine compares them with a golden reference board to decide PASS / FAIL for every part (OK, MISSING, WRONG type, EXTRA).
ภาษาไทย: โมเดล YOLO26 สำหรับตรวจจับชิ้นส่วนอิเล็กทรอนิกส์ 11 ชนิดบนแผ่น PCB ใช้ในเครื่องตรวจจับความสมบูรณ์ของแผ่น PCB ด้วยปัญญาประดิษฐ์ ของมหาวิทยาลัยเทคโนโลยีราชมงคลธัญบุรี โมเดลหลักคือ
new_dataset_v6_split_v1_aug_v2_m/weights/best.pt(mAP50 98.8% และ F1 98.1% บนชุดทดสอบ) ส่วนรุ่นล่าสุดคือ v7

Which file to use
| Model | Path | Notes |
|---|---|---|
| Main model (v6) | new_dataset_v6_split_v1_aug_v2_m/weights/best.pt | Used on the machine and in the thesis. Evaluated on the held-out test set. |
| Latest (v7) | new_dataset_v7_split_v1_aug_v2_m/weights/best.pt | Same recipe on v7 data (v6 + the data_fix_con set, 40 more images). Validation results only so far. |
Every other folder is an earlier experiment (25 training runs in total), kept with its args.yaml, results.csv and
plots so the work can be traced. Each folder is one run: weights/best.pt, weights/last.pt, training curves,
confusion matrices and sample batches.
Classes
buzzer · capacitor · clock · connector · display · ic · led · potentiometer · resistor · switch · transistor
(class ids 0–10 in this order). Both through-hole and surface-mount parts are labelled. The diode class used in earlier
runs was dropped: it had too few examples to train or measure reliably.
Results
Main model (v6), held-out test set
43 images and 1,372 boxes that were never used for training or model selection, image size 640 px.
| mAP@0.50 | mAP@0.50:0.95 | Precision | Recall | F1 |
|---|---|---|---|---|
| 98.8% | 95.8% | 97.2% | 99.1% | 98.1% |
Per class (test set):
| Class | Precision | Recall | AP50 | AP50-95 |
|---|---|---|---|---|
| buzzer | 96.1 | 100.0 | 99.5 | 97.1 |
| capacitor | 97.5 | 98.8 | 98.7 | 96.0 |
| clock | 92.1 | 100.0 | 93.7 | 93.7 |
| connector | 99.3 | 97.5 | 99.4 | 96.7 |
| display | 97.8 | 98.6 | 99.5 | 97.9 |
| ic | 98.1 | 100.0 | 99.0 | 97.2 |
| led | 97.4 | 98.4 | 99.5 | 97.9 |
| potentiometer | 92.8 | 100.0 | 99.5 | 99.5 |
| resistor | 98.4 | 98.7 | 99.1 | 88.4 |
| switch | 99.3 | 99.6 | 99.5 | 98.7 |
| transistor | 99.9 | 98.7 | 99.4 | 91.0 |
potentiometer has only 2 boxes and clock 12 boxes in the test set, so their numbers move more than the others.
Validation (best epoch of each run)
| Run | Data | mAP@0.50 | mAP@0.50:0.95 | Precision | Recall |
|---|---|---|---|---|---|
v6 new_dataset_v6_split_v1_aug_v2_m | 43 images | 97.2% | 92.7% | 95.4% | 96.6% |
v7 new_dataset_v7_split_v1_aug_v2_m | 47 images | 97.3% | 93.4% | 96.6% | 96.4% |
The two validation sets differ by 4 images, so these rows are not a direct comparison.
Speed (main model, 640 px)
Median time per image (preprocess + inference + postprocess) on 114 real images from the machine:
| Device | Backend | Time / image | Images / s |
|---|---|---|---|
| NVIDIA Jetson Orin Nano (on the machine) | CUDA | 72.6 ms | 13.4 |
| Apple Silicon Mac | MPS | 26.4 ms | 38.1 |
Training
| Base model | yolo26m.pt (pretrained, transfer learning) |
| Image size / batch | 640 / 16 |
| Epochs | 60 (patience 20); v6 best at epoch 46 |
| Optimizer | auto, lr0 0.01, lrf 0.01, momentum 0.937, weight decay 0.0005, warmup 3 |
| Online augmentation | mosaic 1.0 (off for the last 10 epochs), fliplr 0.5, hsv 0.02 / 0.8 / 0.4, scale 0.5, translate 0.1 |
| Hardware | Apple Silicon Mac, PyTorch MPS, AMP |
| Time | v6 2.2 h · v7 2.5 h |
Data
Photos of real boards, labelled for this project and split before augmentation:
| v6 train | v6 valid | v6 test | v7 train | v7 valid | v7 test | |
|---|---|---|---|---|---|---|
| Original images | 344 | 43 | 43 | 376 | 47 | 47 |
| Images used | 1,032 | 43 | 43 | 1,128 | 47 | 47 |
| Boxes | 33,843 | 1,293 | 1,372 | 36,525 | 1,401 | 1,494 |
Offline augmentation, train split only, ×3 (the original plus 2 copies): horizontal and vertical flips, 90° / 180° /
270° rotations, brightness ±15 and exposure ±10%, seed 42. v7 is v6 merged with the data_fix_con set, each image
kept in its original split; no exact or near-duplicate images were found across the two sources or across splits.
Usage
from huggingface_hub import hf_hub_download
from ultralytics import YOLO
weights = hf_hub_download(
"Moszer777/pcb-aoi-yolo-rmutt",
"new_dataset_v6_split_v1_aug_v2_m/weights/best.pt",
)
model = YOLO(weights)
result = model.predict("board.jpg", imgsz=640, conf=0.25)[0]
for box in result.boxes:
name = result.names[int(box.cls)]
x1, y1, x2, y2 = box.xyxy[0].tolist()
print(name, round(float(box.conf), 3), ((x1 + x2) / 2, (y1 + y2) / 2))
On the machine the detections are matched to a golden reference: each reference point takes the nearest unclaimed detection within 50 px; the same type is OK, a different type is WRONG, none is MISSING, and leftover detections are EXTRA. Any MISSING or WRONG (or EXTRA, when enabled) makes the point FAIL. The machine also takes several frames per point (default 5) and counts a part as present when it is found in at least 80% of them.
Limitations
- Trained on the boards and lighting of this project. Other boards, cameras or lighting need new data to reach the same accuracy.
- The scores above are box detection scores. Board-level PASS / FAIL accuracy depends on the reference profile and the matching settings and has to be measured on real good and faulty boards.
- No
diodeclass. max_detis 300 per image (YOLO26 default); a single frame with more parts than that will miss some.
Links
- Project site: https://rmutt-pcb-aoi-landing.vercel.app
- Training dashboard (all runs): https://pcb-training-dashboard.vercel.app
- Source code: https://github.com/moszer/PCB_DETECT_RMUTT_GUI
Department of Electronics and Telecommunication Engineering, Faculty of Engineering, Rajamangala University of Technology Thanyaburi (RMUTT), 2026.