สร้างโมเดล 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 ได้สบตาน้องบ่อยๆ 😍

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

อ้างอิง

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Nuttaset kuapanich
Nuttaset kuapanich

Written by Nuttaset kuapanich

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

No responses yet

Write a response