# ตรวจหาพัสดุ: ภาพ → ฝึก → ส่งออก → ทดลองบน PC → ต่อกับ edge

ชุดฝึก Drone-Hub วันที่ 7 กันยายน 2569 ใช้ Python 3.10 ขึ้นไป ไม่มีไลบรารีเพิ่มเติมในขั้นพื้นฐาน ใช้ Windows (`python`) หรือ Linux (`python3`) แตก ZIP ก่อนแล้วเปิด terminal ในโฟลเดอร์นี้

## สิ่งที่ได้ทดลองจริง

เราใช้ภาพสังเคราะห์สี่เหลี่ยมสีน้ำตาล 24 ภาพ ขนาด 64×64 พิกเซล มีภาพไม่มีพัสดุในทุกชุด แบ่ง train 16, val 4, test 4 จาก seed 27 ภาพนี้สร้างขึ้นใหม่ ไม่มีภาพบุคคลหรือข้อมูลส่วนบุคคล

โมเดลพื้นฐานเรียนค่าเฉลี่ย RGB ของพิกเซลพัสดุและฉากหลังจาก train เท่านั้น แล้วจำแนกแต่ละพิกเซลด้วยระยะจากค่าเฉลี่ยและรวมเป็นกรอบหนึ่งกรอบ เป็น nearest-centroid classifier ขนาดเล็ก ไม่ใช่ YOLO และตรวจพัสดุหลายชิ้นแยกกันไม่ได้ ผลผ่านบนภาพสังเคราะห์ไม่บอกความแม่นยำบนภาพจริง

## เริ่มให้จบหนึ่งรอบ (ประมาณ 10–20 นาที)

```console
python parcel_lab.py generate
python parcel_lab.py train
python parcel_lab.py evaluate
python parcel_lab.py infer --image dataset/ppm/test/test-00.ppm
```

1. `generate` สร้าง PNG สำหรับเปิดดู, PPM สำหรับตัวอย่าง Python, label แบบ YOLO และ `dataset.yaml` ที่ชี้มาที่ตำแหน่งบนเครื่องคุณ การรันซ้ำเขียนทับเฉพาะไฟล์ตัวอย่างชื่อเดิม อย่าเก็บภาพจริงไว้ทับชื่อเหล่านี้
2. `train` เรียนจากภาพ train แล้วส่งออก `output/model.json` เปิดอ่านค่า `centroids` ได้ โมเดลนี้เป็น JSON ไม่ใช่ ONNX
3. `evaluate` อ่านโมเดลจากไฟล์อีกครั้งและทดสอบ test 4 ภาพ ต้องได้ `passed: true` และ `exact_match: true` ทั้ง 4 แถว ไม่ใช่ค่า mAP
4. `infer` ให้กรอบ `[ซ้าย, บน, ขวา, ล่าง]` หน่วยพิกเซล ด้านขวาและล่างเป็นขอบที่ไม่รวมพิกเซล ถ้าไม่พบจะได้ `null`

ผลตัวอย่างจริงที่แนบอยู่ใน `output/test-results.json` รันใหม่เพื่อยืนยันบนเครื่องตนเอง ภาพ PNG เปิดดูได้ที่ `dataset/images/` ค่า label หนึ่งบรรทัดคือ `class x_center y_center width height` โดยพิกัดหารด้วยความกว้าง/สูงภาพให้อยู่ช่วง 0–1

## เปลี่ยนเป็นภาพจริงและ YOLO (ยังไม่ได้รันในรอบนี้)

ถ่ายภาพกล่องพัสดุบนโต๊ะหลายมุมและสภาพแสง พร้อมภาพไม่มีพัสดุ ขอสิทธิ์ใช้ภาพก่อนนำเข้าชุดข้อมูล แยก train/val/test ตามรอบถ่ายหรือสถานที่เพื่อไม่ให้ภาพเกือบเหมือนกันข้ามชุด วาดกรอบด้วยเครื่องมือ annotation แล้วส่งออก YOLO format ชื่อ PNG/JPG ต้องตรงกับชื่อ TXT ภายใต้ `images/<split>` และ `labels/<split>`

ใช้โฟลเดอร์ `real-dataset` แยกจากข้อมูลสังเคราะห์ และ YAML ใหม่ตามตัวอย่าง `dataset.yaml` ตรวจภาพกับกรอบด้วยตาก่อนฝึก โมเดลที่ฝึกจากภาพสังเคราะห์ 24 ภาพใช้สาธิตคำสั่งเท่านั้น

สร้าง venv ด้วย Python รุ่นที่ PyTorch รองรับในระบบคุณ (แนะนำตรวจ Python 3.12 ใน WSL/Linux หาก Python 3.14 ติดตั้ง wheel ไม่ได้):

```console
python -m venv .venv
```

Windows ใช้ `.venv\Scripts\python -m pip install ultralytics onnx onnxruntime` และเรียก `.venv\Scripts\yolo` แทน `yolo` ด้านล่าง Linux ใช้ `.venv/bin/python -m pip install ultralytics onnx onnxruntime` แล้วเรียก `.venv/bin/yolo` แพ็กเกจดาวน์โหลดจากอินเทอร์เน็ตและใช้พื้นที่หลาย GB ให้บันทึกรุ่นด้วย `python -m pip freeze` จาก venv หลังติดตั้ง

```console
yolo detect train model=yolo11n.pt data=dataset.yaml epochs=5 imgsz=64 batch=4 device=cpu project=runs name=parcel
yolo export model=runs/parcel/weights/best.pt format=onnx imgsz=64 dynamic=False
yolo predict model=runs/parcel/weights/best.onnx source=dataset/images/test imgsz=64 device=cpu save=True
```

ตัวอย่าง 5 epochs นี้ตรวจขั้นตอนด้วยข้อมูลสังเคราะห์ ไม่ใช่สูตรฝึกสำหรับงานจริง เปลี่ยน YAML, image size และระยะฝึกตามข้อมูลจริง ไฟล์ weight เริ่มต้นอาจดาวน์โหลดอัตโนมัติ ถ้าชื่อ run ซ้ำให้ดูเส้นทางที่โปรแกรมรายงานจริงแล้วแก้คำสั่ง export/predict ตามนั้น คาดว่าจะได้ `best.pt`, `best.onnx` และภาพที่มีกรอบใน `runs/detect/predict*` แต่ไฟล์เหล่านี้ไม่รวมใน ZIP เพราะยังไม่ได้ฝึก YOLO

## ย้ายไป Raspberry Pi / Jetson หลัง PC ผ่าน

ทางพื้นฐาน: คัดลอก `parcel_lab.py`, `output/model.json` และ PPM ทดสอบไปยังโฟลเดอร์โครงสร้างเดิมบน edge แล้วรัน `python3 parcel_lab.py infer --image ...` ใช้ CPU และไม่ต้องติดตั้งแพ็กเกจเพิ่ม ส่วนนี้ยังไม่ได้ทดลองบนบอร์ดจริง

ทาง YOLO: คัดลอก ONNX พร้อมภาพ test ชุดเดิม ติดตั้ง runtime ตามคู่มือบอร์ดแล้วเทียบผลกับ PC ก่อนใช้กล้องจริง Pi เริ่มที่ CPU; Jetson ต้องเลือกแพ็กเกจให้ตรง JetPack ไม่ควรคัดลอก venv จาก Windows ไปใช้ วัด latency, RAM, อุณหภูมิ และผลพลาดก่อนเพิ่ม live camera โดยแยกจากการควบคุมการบิน

## ถ้าติดขัด

- หาไฟล์ไม่พบ: แตก ZIP ก่อน รัน `generate` ตามด้วย `train` และตรวจว่า `--image` เป็น path ที่มีจริง
- PPM อ่านไม่ได้: ตัวอ่านรับเฉพาะ P6 RGB ไม่มี comment, max value 255; PNG ใช้เปิดดูหรือ YOLO ไม่ใช่ input ของตัวอ่านนี้
- มีกรอบใหญ่ทั้งภาพหรือรวมหลายกล่อง: เป็นข้อจำกัดของสีและกรอบเดียว ลองฉากหลังสีน้ำตาลเพื่อเห็น failure mode แล้วใช้โมเดล detection บนภาพจริง
- `No matching distribution` ใน YOLO: ตรวจรุ่น Python/OS/CPU กับเอกสาร PyTorch แล้วสร้าง venv ด้วยรุ่นที่รองรับ ไม่แก้ Python ระบบ
- ONNX import/export ล้มเหลว: บันทึก traceback, เวอร์ชันแพ็กเกจ และลอง inference `.pt` บน PC ก่อน คู่มือ export เป็นจุดตรวจถัดไป

## ที่มาและใบอนุญาต

Source/ภาพสังเคราะห์/โมเดล JSON ที่สร้างในชุดนี้ใช้ MIT ตาม `LICENSE.txt` ไม่รวมซอฟต์แวร์และ weight ภายนอก Ultralytics ใช้ AGPL-3.0 หรือ Enterprise ตามเงื่อนไขเจ้าของ อ่านก่อนนำงานไปเผยแพร่หรือรวมกับผลิตภัณฑ์ คู่มือตรวจเมื่อ 2026-09-07:

- [Ultralytics dataset format](https://docs.ultralytics.com/datasets/detect/)
- [Detection train/predict](https://docs.ultralytics.com/tasks/detect/)
- [Export](https://docs.ultralytics.com/modes/export/)
- [Raspberry Pi](https://docs.ultralytics.com/guides/raspberry-pi/)
- [Jetson](https://docs.ultralytics.com/guides/nvidia-jetson/)
- [Ultralytics license](https://www.ultralytics.com/license)

ไม่มีผลทดลองจากผู้เรียนจริงในชุดนี้ ใช้ `pilot-feedback.csv` จากหน้าดาวน์โหลดบันทึกรอบทดลองของคุณ
