Categories
Computer Data

ทำ Synthetic Head Pose Dataset เพื่อเทรน AI

การเทรน Deep Learning (เช่น Head Pose Estimation) ต้องการข้อมูลที่มีจำนวนมาก แต่ปัญหาคือไม่มี Dataset ขนาดนั้น วิธีหนึ่งที่เพิ่มข้อมูลได้คือ Synthetic Dataset

ปกติเวลาที่เทรนโมเดล AI ที่เป็น Deep Learning สิ่งหนึ่งที่โมเดลเหล่านี้ต้องการสำหรับการเทรนโมเดลคือข้อมูล Dataset สำหรับการฝึกที่มีข้อมูลเป็นจำนวนมาก อย่างไรก็ตามปัญหาหนึ่งคือไม่มี Dataset ที่มีจำนวนมากพอสำหรับการเทรน

วิธีทั่วไปที่ทำก็ออกไปเก็บข้อมูล และจัดทำ Ground Truth สำหรับการเทรนโมเดล AI เพิ่ม ซึ่งโอเค อย่างไรก็ดีมีอีกวิธีหนึ่งที่เราสามารถทำได้คือการสังเคราะห์ชุดข้อมูล Dataset ขึ้นมา (หรือเรียกว่าทำ Synthetic Dataset)

ตัวอย่างงานสำหรับการทำ Synthetic Dataset คืองานทางด้าน Head Pose Estimation ที่เป็นงานวัดการเคลื่อนไหวของใบหน้าเมื่อเทียบกับกล้องแล้วแสดงค่าออกมาเป็นองศาของการขยับศีรษะ

องศาจะแสดงผลทั้ง 3 ทิศทาง ได้แก่ ก้ม-เงยศีรษะ (Pitch) หันศีรษะซ้าย-ขวา (Yaw) และเอนศีรษะซ้าย-ขวา (Roll)

Head Pose Estimation ที่ให้ผลลัพธ์ออกมาเป็นองศาการหันศีรษะ 3 ทิศทาง ได้แก่ yaw, pitch และ roll

การเทรน Head Pose Estimation ในปัจจุบันที่เราจะใช้ Deep Learning ในการเทรน ตัวอย่างเทคนิคที่ใช้ได้แก่ HopeNet, FSA-Net จุดนี้ตัวโมเดล Deep Learning จำเป็นต้องมีข้อมูล Dataset ที่มีจำนวนมากพอต่อการเทรน โดยตัวอย่างข้อมูล Dataset ที่เกิดจากการทำ Synthetic Dataset ที่เปเปอร์กล่าวถึงกันคือ 300W_LP

300W_LP เป็น Dataset ที่ผ่านการสร้างข้อมูล Dataset การขยับศีรษะให้มีองศาที่กว้าง และมีจำนวนข้อมูลที่เยอะมากกว่าเดิม โดยสร้างจาก Dataset ทั้ง 4 Dataset ได้แก่ AFW, HELEN, IBUG และ LFPW และสร้างได้โดยที่ได้จำนวนข้อมูลทั้งหมด 61,225 ภาพ และได้กลับภาพซ้าย-ขวา (Flip) ทำให้ได้จำนวนข้อมูลทั้งหมด 122,450 ภาพ

สำหรับเทคนิคการทำ Synthetic Dataset สำหรับ Dataset นี้ก็มาจากเทคนิค 3DDFA (3D Dense Face Alignment) ที่มีคนเผยแพร่โค้ดสำหรับการทำ Synthetic Dataset ที่มีชื่อว่า IBUG Face Pose Augmentation บน GitHub เครื่องมือนี้เป็นเครื่องมือสำหรับการทำ Synthetic Dataset โดยเราสามารถเลือกองศาที่ต้องการใบหน้าในภาพหันศีรษะไปในองศาที่ต้องการได้ครับ

วิธีการทำ Face Detection และจุด Facial Landmark

ก่อนจะทำ Synthetic Dataset ผู้อ่านจำเป็นต้องมีรูปภาพที่มีใบหน้าคน และมีจุด Facial Landmark เสียก่อน แต่ถ้ายังไม่มีจุด Facial Landmark ผู้อ่านสามารถหาจุด Facial Landmark ได้โดยใช้เทคนิค Face Detection และ Facial Landmark Detection

ในตัวอย่างนี้จะใช้ไลบรารี IBUG Face Detection และ IBUG Face Alignment ที่ใช้เทคนิคการทำ Face Detection โดย RetinaFace และใช้เทคนิคการหา Facial Landmark โดย FAN (Face Alignment Network) ตามลำดับ

แต่ก่อนอื่น เราจะต้องติดตั้งไลบรารีเสียก่อน ทำได้ตามด้านล่างนี้ครับ

ติดตั้งแพคเกจ Face Detection

git clone https://github.com/hhj1897/face_detection.git
cd face_detection
git lfs pull
pip install -e .

ติดตั้งแพคเกจ Face Alignment

git clone https://github.com/hhj1897/face_alignment.git
cd face_alignment
pip install -e .

ต่อมาโหลดภาพสำหรับการหา Facial Landamark ส่วนนี้ทำได้โดยการพิมพ์โค้ดตามด้านล่างนี้่ครับ

นำเข้าไลบรารี

ส่วนแรกเป็นการนำเข้าไลบรารีที่เราติดตั้งเข้ามา รวมถึงไลบรารี OpenCV

import cv2
from ibug.face_detection import RetinaFacePredictor
from ibug.face_alignment import FANPredictor

โหลดโมเดล

ส่วนที่สองเป็นการโหลดโมเดล Face Detection และ Face Alignment

face_detector = RetinaFacePredictor(
    threshold=0.8, device='cuda:0',
    model=RetinaFacePredictor.get_model('resnet50'))

landmark_detector = FANPredictor(
    device='cuda:0', model=FANPredictor.get_model('2dfan2_alt'))

จากข้างบน

  • ตัวโค้ดจะโหลดโมเดล Face Detection และ Facial Landmark Detection โดยกำหนด Threshold ของ Face Detection ว่าให้ได้ค่า Confidence มากกว่า 0.8 ขึ้นไป
  • ตัวโค้ดกำหนดให้ใช้การ์ดจอตัวแรกสำหรับการทำ Face Detection และ Facial Landmark Detection ผ่านการพิมพ์ cuda:0 ตรง device

โหลดภาพและทำ Face Detection + หา Facial Landmark

ต่อมาโหลดภาพจากเครื่องด้วยคำสั่ง imread ของ OpenCV แล้วให้ Face Detection หาตำแหน่งใบหน้าจากภาพ ร่วมกับการใช้ Face Alignment หา Facial Landmark

ตัวอย่างรูปสามารถดาวน์โหลดได้จาก Wikipedia Commons เมื่อดาวน์โหลดรูปแล้วให้เปลี่ยนชื่อเป็น test.jpg (หรือชื่ออื่น ๆ ได้ตามผู้อ่าน)

ตัวอย่างภาพ (ดาวน์โหลดมาจาก Wikipedia Commons)
# โหลดรูปภาพ
image = cv2.imread('test.jpg')

# ค้นหาใบหน้าจากภาพ
# โดยเราตั้งค่าพารามิเตอร์ rgb ว่าภาพที่โหลดเป็น RGB หรือไม่ ถ้าใช่ตอบ True ถ้าไม่ตอบ False โดยตัว OpenCV แล้วภาพที่โหลดจะเป็น BGR ให้ตอบ False
# ผลลัพธ์ที่ได้แสดงในรูปตัวแปร Array ที่มีขนาด Nx15
detected_faces = face_detector(image, rgb=False)

# ค้นหา Facial Landmark
# ผลลัพธ์ที่ได้แสดงในรูปตัวแปร Array ที่มีขนาด Nx68x2
landmarks, scores = landmark_detector(image, detected_faces, rgb=False)

เมื่อได้ตำแหน่งใบหน้าในภาพ ร่วมกับได้ Facial Landmark แล้ว ผู้อ่านจะ Crop ภาพใบหน้าหรือไม่ก็ได้ ในตัวอย่างนี้เราจะ Crop ภาพใบหน้าครับ

ขั้นแรก หาตำแหน่งใบหน้าและ Facial Landmark จากภาพสำหรับการ Crop ใบหน้า

# Get BBOX and Facial Landmark Result
x_min,y_min,x_max,y_max = detected_faces[0][:4]

# Crop Face
img_h, img_w = image.shape[:2]
w = x_max - x_min
h = y_max - y_min
ad = 0.4
x_min = max(int(x_min - ad * w), 0)
x_max = min(int(x_max + ad * w), img_w - 1)
y_min = max(int(y_min - ad * h), 0)
y_max = min(int(y_max + ad * h), img_h - 1)

ขั้นตอนที่สอง Crop ใบหน้า และ Crop จุด Facial Landmark

cropped_image = image[y_min:y_max, x_min:x_max]

# Crop Landmark

landmark = landmarks[0]
landmark[:, 0] -= x_min
landmark[:, 1] -= y_min

เมื่อครอบใบหน้าแล้ว จุดนี้เราจะมีข้อมูลสำหรับการทำ Synthetic Dataset แล้วครับ

วิธีการทำ Synthetic Dataset

การติดตั้งไลบรารี

ก่อนจะเริ่มทำ Synthetic Dataset เราจะต้องดาวน์โหลด repo ของ IBUG Face Pose Augmentation เสียก่อนด้วยคำสั่ง git clone

git clone --recurse-submodules https://github.com/hhj1897/face_pose_augmentation.git

จากโค้ดข้างบนจะสังเกตว่ามีการใส่ออฟชัน –recurse-submodules ร่วมด้วย อันนี้จะเป็นการดาวน์โหลดตัวโค้ด 3DDFA มาใช้สำหรับการหา 3D Morphable Model กับภาพที่เราต้องการนำมาทำ Synthetic Dataset

ขั้นตอนถัดไป เป็นการติดตั้งไลบรารี จุดนี้ทำได้โดยเข้าไปที่โฟลเดอร์ที่เราดาวน์โหลดโค้ดมา หลังจากนั้นใช้คำสั่งไพทอนสำหรับการติดตั้งไลบรารี

cd face_pose_augmentation
pip install -r requirements.txt
pip install -e .

ต่อมาเขียนโค้ด ส่วนแรกที่จะเขียนเป็นการนำเข้าไลบรารีสำหรับการทำ Synthetic Dataset

นำเข้าไลบรารี

ขั้นตอนแรกเป็นการนำเข้าไบรารีด้วยคำสั่ง import

from ibug.face_pose_augmentation import TDDFAPredictor, FacePoseAugmentor
import numpy as np

โหลดโมเดล

ต่อมา เมื่อไลบรารีได้รับการโหลดเข้ามาแล้วก็ใช้คำสั่งตามด้านล่างนี้เพื่อโหลดโมเดล 3DDFA และโหลดเครื่องมือสำหรับการทำ Synthetic Dataset

# Instantiate 3DDFA
tddfa = TDDFAPredictor(device='cuda:0')

# Create the face pose augmentor
augmentor = FacePoseAugmentor()

การทำ Synthetic Dataset

ต่อมาเป็นการใช้คำสั่งเพื่อที่จะหา 3D Morphable Model สำหรับภาพที่ได้รับการ label ด้วย Facial Landmark ที่มีจำนวน Landmark ทั้งหมด 68 จุด โดยเราสามารถใช้ภาพที่หาจุด Facial Landmark แล้วในหัวข้อก่อนหน้ามาใช้ได้เลย

รายละเอียดของคำสั่งก็แสดงตามด้านล่างนี้

tddfa_result = TDDFAPredictor.decode(tddfa(cropped_image, landmark, rgb=False))[0]

ผลลัพธ์ของการหา 3D Morphable Model ตามโค้ดข้างบนจะแสดงตามด้านล่างนี้

{  
    'roi_box': '< ตำแหน่งใบหน้าในภาพ >', 
    'params': '< พารามิเตอร์ 3D Morphable Model >',
    'vertex': '< vertex >',
    'pts68': '< จุด Facial Landmark 3 มิติ >',
    'face_pose': {
        'pitch': < Pitch >, 'yaw': < Yaw >, 'roll': < Roll >, 
        't3d': < 3D Translation Matrix >, 
        'f': < Scale Factor >
    }, 
    camera_transform': {
        'fR': < Rotation Matrix >, 
        'T': < Translation Matrix >
    }
}

เมื่อได้ 3D Morphable Model จากการใช้คำสั่งข้างบนนี้แล้ว ขั้นตอนต่อมาจะเป็นการสร้างภาพที่มีองศาที่ต้องการ

ส่วนนี้ทำได้โดยการใช้คำสั่งที่อธิบายตามด้านล่างนี้

ในตัวอย่างจะกำหนดให้ใบหน้าหันไปทางขวา 45 องศา

augmentation_results = augmentor(
    cropped_image, 
    tddfa_result, 
    np.array([0, -45 * np.pi / 180, 0]), 
    landmark
)

อธิบายส่วน delta pose อันนี้จะเป็นผลต่างขององศาการหันศีรษะในปัจจุบัน กับองศาของการหันศีรษะที่ต้องการ โดยจะเขียนในรูป Array ตามด้านล่างนี้ครับ

ค่าองศาที่เขียนใน Array จะต้องเป็นหน่วยเรเดียน (radian)

[< องศาก้มศีรษะ pitch >,< องศาหันศีรษะซ้าย-ขวา yaw>,< องศาเอนศีรษะซ้าย-ขวา roll >]

ผลลัพธ์ที่ได้จากการใช้คำสั่งเพื่อทำ Synthetic Dataset จะอยู่ในรูปตัวแปร Dictionary ครับ รายละเอียดแสดงตามด้านล่างนี้

{
    'correspondence_map': < ผลลัพธ์การทำ 2D-3D correspondence >, 
    'warped_landmarks': {
         '3d_style': < ผลลัพธ์ 3D facial landmark >, 
         '2d_style': < ผลลัพธ์ 2D facial landmark >,
         'projected_3d': < ผลลัพธ์ของ Facial Landmark ที่แปลงเป็น 3 มิติ >, 
         'refined_2d': < ผลลัพธ์ Facial Landmark ที่เป็น 2 มิติ >
    }, 
    'warped_image': < ตัวแปร array ภาพที่ได้รับการทำ Synthetic Dataset >
}

สำหรับภาพผลลัพธ์แสดงตามด้านล่างนี้

ภาพด้านซ้ายเป็นภาพต้นฉบับที่ผ่านการ Crop ใบหน้า ส่วนภาพด้านขวาเป็นภาพผลลัพธ์ของการทำ Synthetic Dataset

จากผลลัพธ์ที่ได้ก็พบว่าเราสามารถทำ Synthetic Dataset สำหรับทำ Head Pose Estimation ได้ครับ โดยในตัวอย่างจะใช้ภาพ 1 ภาพ อย่างไรก็ตามเนื่องจากการเทรนโมเดลจำเป็นต้องใช้ข้อมูลเป็นจำนวนมาก อันนี้ผู้อ่านจำเป็นต้องหาภาพจำนวนมากสำหรับการทำ Synthetic Dataset ครับ

กรณีที่หาภาพลักษณะนี้ไม่เจอ แนะนำให้ดาวน์โหลด Dataset อย่าง 300W มาทำ Synthetic Dataset ตามที่ Dataset 300W_LP ทำได้ครับ

By Kittisak Chotikkakamthorn

อดีตนักศึกษาฝึกงานทางด้าน AI ที่ภาควิชาวิศวกรรมไฟฟ้า มหาวิทยาลัย National Chung Cheng ที่ไต้หวัน ที่กำลังหางานทางด้าน Data Engineer ที่มีความสนใจทางด้าน Data, Coding และ Blogging / ติดต่อได้ที่: contact [at] nickuntitled.com