สร้างโมเดล Object Detection ตรวจจับหน้าแมว 😸

Nuttaset kuapanich
4 min readMar 19, 2024

--

เนื้อหาในนี้สามารถอ่านแล้วทำตามไปด้วยได้เลย😎 แต่ก็ข้ามพื้นฐานหลายอย่าง ถ้าต้องการศึกษาพื้นฐานก่อน สามาถอ่านลิงค์นี้ได้ครับ

ผมเชื่อว่าหลายท่านน่าจะมีน้องแมวขี้อ้อนแสนน่ารักอยู่ที่บ้าน และหลายท่านก็อยากถ่ายทอดความน่ารักของน้องให้คนอื่นได้เห็น 🥰 เรามาลองถ่ายทอยความน่ารักของน้องให้ AI ได้เห็นกันดีมั้ยครับ!

สร้างโมเดล Object Detection ให้ AI ได้สบตากับน้องมากขึ้น ได้เห็นน้องบ่อยๆ และตกหลุมรักเช่นเดียวกับพวกเรา~

ผมเอา dataset มาจาก Kaggle ในนี้มีรูปน้องมากกว่า 5 หมื่นภาพ! 🙀 โดยใช้ MMDetection เป็นเครื่องมือในการสร้าง และทำบนระบบปฏิบัติการ Linux การติดตั้ง libray ที่ต้องใช้ สามารถดูได้ใน ลิงค์นี้ครับ

ขั้นตอนการทำแบ่งออกเป็น 3 ขั้นตอนหลักๆดังนี้

  1. เตรียม Dataset
  2. Train Model
  3. ใช้งาน Model

ก่อนอื่นเครื่องเราต้องมี library ที่จำเป็นต้องใช้ก่อน คือ PyTorch, MMDetection สามารถดูวิธีติดตั้งได้ ที่นี่ และ scikit-learn กรณีใช้ cona ติดตั้งโดยใช้คำสั่ง

conda install scikit-learn 

1. เตรียม Dataset

หลังจากโหลด dataset มา ข้อมูลจะอยู่ใน result-dataset/result-dataset/ คือ coco.json และโฟลเดอร์ data ที่มีรูปน้องอยู่ 5,1453 ภาพ

เนื่องจากไฟล์ json มีอยู่ไฟล์เดียว ดังนั้นเราต้องแบ่งข้อมูลออกเป็น train, valid, test เอง

import json
from sklearn.model_selection import train_test_split

# เปิดไฟล์ และอ่านค่าจาก coco.json
with open("result-dataset/result-dataset/coco.json", 'r') as file:
data = json.load(file)

# เก็บรายชื่อไฟล์รูปภาพไว้ใน img_list
img_list = data["images"]

# แบ่งข้อมูลออกเป็น train:70%, valid:15%, test:15%
train_data, temp_data = train_test_split(img_list, test_size=0.3, random_state=42)
valid_data, test_data = train_test_split(temp_data , test_size=0.5, random_state=42)

# นำข้อมูลเก็บในตัวแปรใหม่ เพื่อเตรียมบันทึกในไฟล์ json
train_dict = {
"annotations": data["annotations"].copy(),
"categories": data["categories"].copy(),
"images": train_data
}

valid_dict = {
"annotations": data["annotations"].copy(),
"categories": data["categories"].copy(),
"images": valid_data
}

test_dict = {
"annotations": data["annotations"].copy(),
"categories": data["categories"].copy(),
"images": test_data
}

# บันทึกไฟล์ json ใหม่
with open("result-dataset/result-dataset/train.json", 'w') as file:
json.dump(train_dict, file)

with open("result-dataset/result-dataset/valid.json", 'w') as file:
json.dump(valid_dict, file)

with open("result-dataset/result-dataset/test.json", 'w') as file:
json.dump(test_dict, file)

เมื่อเสร็จจะได้ไฟล์ใหม่ออกมาคือ train.json, valid.json และ test.json ข้อมูลของเราก็พร้อมสำหรับการ train model เป็นที่เรียบร้อย

2. Train Model

ก่อนอื่นเราต้องเข้าไปแก้ไขชื่อ class ในไฟล์ mmdetection/mmdet/datasets/coco.py ให้ตรงกับที่ระบุในไฟล์ json โดยในไฟล์ json ระบุชื่อ class นี้ว่า “face” ดังนั้นใน coco.py ที่ METAINFO['classes'] ระบุว่า 'face', ดังภาพด้านล่าง

ต่อมาโหลด pretrained model เพื่อทำการ transfer learning โดยโมเดลที่ผมเลือกใช้คือ Cascade R-CNN, สามารถโหลดได้จาก ลิงค์นี้

หรือเพื่อความรวดเร็วสามารถสั่งผ่าน command line ว่า

wget https://download.openmmlab.com/mmdetection/v2.0/cascade_rcnn/cascade_rcnn_x101_64x4d_fpn_20e_coco/cascade_rcnn_x101_64x4d_fpn_20e_coco_20200509_224357-051557b1.pth
ภาพระหว่างโหลด pretrained model ลงเครื่อง

เมื่อโหลดเสร็จจะได้ไฟล์ชื่อว่า

cascade_rcnn_x101_64x4d_fpn_1x_coco_20200515_075702-43ce6a30.pth

หลังจากนั้นแก้ไขค่าใน config file โดยใช้ config file ที่ตรงกับโมเดลที่โหลด

from mmengine.config import Config

# อ่าน config file ของโมเดลที่จะใช้
cfg = Config.fromfile("mmdetection/configs/cascade_rcnn/cascade-rcnn_x101-64x4d_fpn_1x_coco.py")

# กำหนดจำนวน class
for bbox_head in cfg.model.roi_head.bbox_head:
bbox_head.num_classes = 1

# กำหนดเป็น auto scale learning rate และ batch size
cfg.auto_scale_lr.base_batch_size = 4
cfg.auto_scale_lr.enable = True
cfg.auto_scale_lr.base_batch_size, cfg.auto_scale_lr.enable

# กำหนด path ของข้อมูล ทั้ง train, valid และ test
cfg.data_root = "result-dataset/result-dataset/"
cfg.train_dataloader.dataset.data_root = "result-dataset/result-dataset/"
cfg.train_dataloader.dataset.data_prefix.img = "data"
cfg.train_dataloader.dataset.ann_file = "train.json"
cfg.val_dataloader.dataset.data_root = "result-dataset/result-dataset/"
cfg.val_dataloader.dataset.data_prefix.img = "data"
cfg.val_dataloader.dataset.ann_file = "valid.json"
cfg.test_dataloader.dataset.data_root = "result-dataset/result-dataset/"
cfg.test_dataloader.dataset.ann_file = "test.json"
cfg.test_dataloader.dataset.data_prefix.img = "data/"
cfg.val_evaluator.ann_file = "result-dataset/result-dataset/valid.json"
cfg.test_evaluator.ann_file = "result-dataset/result-dataset/test.json"

# กำหนดจำนวน epoch
cfg.train_cfg.max_epochs = 5

# กำหนด pretrained model ที่จะใช้
checkpoint_file = "cascade_rcnn_x101_64x4d_fpn_20e_coco_20200509_224357-051557b1.pth"
cfg.load_from = checkpoint_file

# บันทึก config file หลังแก้ไข
cfg.dump('my_config.py')

สั่ง train โมเดล โดยระบุว่าใช้ GPU หมายเลข 2 (ไม่ใส่ CUDA_VISIBLE_DEVICES ก็ได้)

CUDA_VISIBLE_DEVICES=2 python mmdetection/tools/train.py my_config.py --auto-scale-lr --work-dir=train_result/ > train_log.txt 2>&1

เมื่อ train โมเดลเสร็จจะได้ผลลัพธ์เก็บไว้ที่ train_result/ ตามที่ระบุเอาวันในคำสั่ง train

เรามาเช็คการเรียนรู้ของโมเดลระหว่างการ train โดยสร้างกราฟ loss function ด้วยคำสั่ง

python mmdetection/tools/analysis_tools/analyze_logs.py plot_curve train_result/20240318_210052/vis_data/scalars.json --keys bbox_mAP --legend bbox_mAP --title "Bounding Box Mean Average Precision" --out bbox_mAP.png

จะได้ภาพผลลัพธ์ออกมาชื่อว่า bbox_mAP.png

bbox_mAP.png

เพราะว่าเป็นสาธิตการทำ ก็เลยสั่ง train แค่ 5 epoch, กราฟอาจจะออกมาแปลกๆ 😅 แต่ก็ถือว่าโมเดลเรียนรู้ได้ดีตั้งแต่ epoch แรกแล้ว

3. ใช้งาน Model

เนื่องจากโมเดลมีค่า bbox mAP สูงสุดตอน epoch ที่ 3 ดังนั้นเราจะนำโมเดลนี้มาใช้

โมเดลหลังจากการ train ทุก epoch จะถูกบันทึกไว้ในโฟลเดอร์ train_result เช่นกัน

ภาพน้องที่ใช้คือตัวอย่างแมวไทย 3 สายพันธุ์ได้แก่

วิเชียรมาศ (Wichianmat)
สีสวาด (Korat)
โกญจา (Bombay)

โดยตั้งชื่อไฟล์ว่า wichianmat.jpg , korat.jpg และ bombay.jpg เก็บไว้ในโฟลเดอร์ img_in/

คำสั่งสำหรับเรียกใช้งานโมเดลคือ

from mmdet.apis import DetInferencer

# โหลดโมเดลที่ train เอาไว้
my_model = DetInferencer(model="my_config.py", weights="train_result/epoch_3.pth", device="cuda")

# นำรูปภาพเข้าไปในโมเดล โดยให้ผลลัพธ์เก็บไว้ที่โฟลเดอร์ img_out
my_model("img_in/wichianmat.jpg", out_dir="img_out/")
my_model("img_in/korat.jpg", out_dir="img_out/")
my_model("img_in/bombay.jpg", out_dir="img_out/")

ภาพที่ออกมาคือ

เท่านี้ก็เสร็จเรียบร้อยแล้วครับสำหรับการฝึกให้ AI ได้สบตาน้องบ่อยๆ 😍

ลองเอาวิธีนี้ไปใช้กับแมวที่บ้านดูครับ~

อ้างอิง

--

--

Nuttaset kuapanich

กำลังศึกษาระดับปริญญาตรี คณะปัญญาประดิษฐ์ มหาวิยาลัยซุนยัดเซ็น Email: kuapanich@mail2.sysu.edu.cn