AI Face Body การตรวจจับท่าทางมือด้วย Python และ Mediapipe
Tags: ai, python
Published: 2024-04-16 08:56:15

## รายละเอียดเกี่ยวกับ AI Code

จะเป็นการใช้ไลบรารี่ Mediapipe เพื่อใช้ในการตรวจจับใบหน้ากับมือและวาด landmark บนใบหน้าหรือมือ รวมทั้งตรวจจับโครงสร้างร่างกายโดยรวม จากภาพวิดีโอจากกล้องเว็บแคม ซึ่งเป็นทำงานเกี่ยวกับ Computer Vision หรือการประมวลผลภาพด้วยวิธีการที่ใช้คอมพิวเตอร์เข้าร่วมกับ ไลบรารี Mediapipe ที่มีการใช้เทคโนโลยีที่ใช้ประโยชน์จากการเรียนรู้ของเครื่อง (Machine Learning) โดยเฉพาะอย่างยิ่งการเรียนรู้เชิงลึก (Deep Learning) เพื่อตรวจจับและวิเคราะห์ภาพและวิดีโออย่างอัตโนมัติ

ไลบรารี่ Mediapipe เป็นการใช้โมเดลที่ถูกฝึก (Train) ด้วยการเรียนรู้ของเครื่องเพื่อแยกรูปแบบและวัตถุในภาพ โดยมีใช้ชุดข้อมูล (Data) ที่มีความหลากหลายและใหญ่ขึ้น ซึ่งช่วยให้โมเดลสามารถรู้จำและตรวจจับวัตถุต่าง ๆ ได้ในสภาวะที่แตกต่างกัน เช่น ใบหน้า มือ, โครงสร้างร่างกาย, และฟีเจอร์อื่น ๆ ในภาพหรือวิดีโอ

## ขั้นตอนที่ 1 Import ไลบรารี่ที่จำเป็นต้องใช้
เริ่มจากการ import mediapipe เเละ cv2 ดังตัวอย่างต่อไปนี้
```
import mediapipe as mp
import cv2
```

> จำเป็นต้องใช้ Python version ที่เหมาะสมกับไลบรารี่ Mediapipe 
> ซึ่งเเนะนำให้ใช้ version 3.8 - 3.11
Version ที่ใช้ในในการทำงานตอนนี้ คือ Python version 3.11.9

## ขั้นตอนที่ 2 การนำเข้าโมดูลของไลบรารี่ Mediapipe โดยกำหนดตัวแปร
โดยกำหนดตัวแปร mp_drawing เเละ mp_holistic เพื่อใช้ในการเรียกโมดูล
```
mp_drawing = mp.solutions.drawing_utils
mp_holistic = mp.solutions.holistic
```
ต่อไปจะการสร้างอ็อบเจกต์ cap ของ cv2.VideoCapture ซึ่งเป็นตัวแทนของกล้องวิดีโอหรืออุปกรณ์ที่ใช้เก็บวิดีโอ 

การสร้าง VideoCapture object ด้วยค่าอาร์กิวเมนต์เป็น 0 หมายถึงการเปิดกล้อง โดยจะใช้กล้องอุปกรณ์ของคอมพิวเตอร์ ดังตัวอย่างต่อไปนี้
```
cap = cv2.VideoCapture(0)
```
สร้างบล็อก (with) เพื่อสร้างอ็อบเจกต์ของโมเดล Holistic จากไลบรารี Mediapipe โดยกำหนดค่าการตรวจจับและการติดตามวัตถุในขั้นตอนการประมวลผลภาพหรือวิดีโอ 

ซึ่งมีค่าการตรวจจับขั้นต่ำ (min_detection_confidence) เป็น 0.5 และค่าการติดตามวัตถุขั้นต่ำ (min_tracking_confidence)  เป็น 0.5 ซึ่งคือค่าความมั่นใจขั้นต่ำที่โมเดลจะใช้ในการตรวจจับและติดตามวัตถุในภาพหรือวิดีโอ

```
with mp_holistic.Holistic(min_detection_confidence=0.5, min_tracking_confidence=0.5) as holistic:

```

## ขั้นตอนที่ 3 ตรวจสอบกล้องหรืออุปกรณ์ เเละนำภาพที่ได้มาแปลงให้เหมาะสม โดยใช้ Cv2

เริ่มการจากตรวจสอบว่ากล้องเปิดอยู่หรือไม่ โดยการเรียกใช้เมธอด isOpened() บนอ็อบเจกต์ cap จะคืนค่า True ถ้ากล้องหรืออุปกรณ์ยังคงเปิดอยู่ และคืนค่า False ถ้ากล้องหรืออุปกรณ์ถูกปิด
```
 while cap.isOpened():
        ret, frame = cap.read()
```
ต่อไปจะเป็นการแปลงภาพ frame ที่มาจากกล้องหรืออุปกรณ์ เพื่อใช้ในการประมวลผลภาพหรือวิดีโอให้เหมาะสม โดยใช้โค้ดต่อไปนี้
```
   image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        
   results = holistic.process(image)
        
   image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
```
บรรทัดที่ 1  เป็นการแปลงภาพ frame ที่มาจากกล้องหรืออุปกรณ์อื่นๆ จากฟอร์แมตสี BGR เป็น RGB ซึ่งเป็นฟอร์แมตสีที่ Mediapipe ใช้ในการประมวลผลภาพ

บรรทัดที่ 2  เป็นการประมวลผลภาพโดยใช้โมเดล Holistic จากไลบรารี Mediapipe โดยให้ภาพ image เป็นอินพุต โมเดลจะทำการตรวจจับและวิเคราะห์คุณลักษณะต่าง ๆ ในภาพ เช่น ใบหน้า โครงสร้างร่างกาย และมือ

บรรทัดที่ 3 เป็นการแปลงภาพที่ได้รับผลลัพธ์จากการประมวลผลกลับมาจากฟอร์แมตสี RGB เป็น BGR เพื่อทำการวาดผลลัพธ์บนภาพต้นฉบับ 

## ขั้นตอนที่ 4 การวาด landmark บนจุดสำคัญและการตรวจจับโครงสร้างร่างกาย ลงบนภาพหรือวิดีโอที่ได้จากกล้องหรืออุปกรณ์อื่น ๆ 

ส่วนนี้ใช้ในการวาด landmark หรือจุดสำคัญบนใบหน้า (face landmarks), มือขวาและมือซ้าย (right hand landmarks และ left hand landmarks) และการตรวจจับโครงสร้างร่างกาย (pose landmarks) ลงบนภาพหรือวิดีโอที่ได้จากกล้องหรืออุปกรณ์ โดยมีรายละเอียดดังนี้

- วาด landmark บนใบหน้า (Face Landmarks) โดยใช้ฟังก์ชัน mp_drawing.draw_landmarks()เพื่อวาด landmark บนใบหน้า เเละกำหนด results.face_landmarks เป็นตำแหน่งของ landmark ที่ตรวจจับได้ โดยใช้ mp_holistic.FACEMESH_TESSELATION เป็นการเชื่อมต่อของ landmark และกำหนดสีและความหนาของเส้นที่ใช้ในการวาด landmark ด้วย mp_drawing.DrawingSpec()

- วาด landmark ของมือขวา (Right Hand Landmarks)  โดยใช้ฟังก์ชัน  mp_drawing.draw_landmarks() แต่ใช้ results.right_hand_landmarks เพื่อกำหนดตำแหน่งของ landmark บนมือขวา

- วาด landmark ของมือซ้าย (Left Hand Landmarks)  โดยใช้ฟังก์ชัน  mp_drawing.draw_landmarks() แต่ใช้ results.left_hand_landmarks เพื่อกำหนดตำแหน่งของ landmark บนมือซ้าย

- วาด landmark ของโครงสร้างร่างกาย (Pose Landmarks) โดยใช้ฟังก์ชัน  mp_drawing.draw_landmarks() แต่ใช้ results.pose_landmarks เพื่อกำหนดตำแหน่งของ landmark บนโครงสร้างร่างกาย 

โดยฟังก์ชัน mp_drawing.draw_landmarks() สามารถปรับแต่งหรือกำหนดสี เเละความหนาของเส้นที่ใช้ในการวาด landmark ได้อย่างเหมาะสมตามที่ต้องการแสดงผล

        

```
# 1. Draw face landmarks
        mp_drawing.draw_landmarks(image, results.face_landmarks, mp_holistic.FACEMESH_TESSELATION, 
                                 mp_drawing.DrawingSpec(color=(80,110,10), thickness=1, circle_radius=1),
                                 mp_drawing.DrawingSpec(color=(80,256,121), thickness=1, circle_radius=1)
                                 )
        
        # 2. Right hand
        mp_drawing.draw_landmarks(image, results.right_hand_landmarks, mp_holistic.HAND_CONNECTIONS, 
                                 mp_drawing.DrawingSpec(color=(80,22,10), thickness=2, circle_radius=4),
                                 mp_drawing.DrawingSpec(color=(80,44,121), thickness=2, circle_radius=2)
                                 )

        # 3. Left Hand
        mp_drawing.draw_landmarks(image, results.left_hand_landmarks, mp_holistic.HAND_CONNECTIONS, 
                                 mp_drawing.DrawingSpec(color=(121,22,76), thickness=2, circle_radius=4),
                                 mp_drawing.DrawingSpec(color=(121,44,250), thickness=2, circle_radius=2)
                                 )

        # 4. Pose Detections
        mp_drawing.draw_landmarks(image, results.pose_landmarks, mp_holistic.POSE_CONNECTIONS, 
                                 mp_drawing.DrawingSpec(color=(245,117,66), thickness=2, circle_radius=4),
                                 mp_drawing.DrawingSpec(color=(245,66,230), thickness=2, circle_radius=2)
                                 )
```

## ขั้นตอนที่ 5 แสดงผลของภาพหรือวิดีโอในโปรแกรม เเละการหยุดการทำงานของโปรแกรม

หลังจากที่ทำภาพมาแปลงเเละวาด landmarks ลงบนภาพเเล้ว ก็จะการแสดงภาพที่ได้จากกล้องหรืออุปกรณ์บนหน้าต่างของโปรแกรม โดยฟังก์ชัน cv2.imshow() โดยกำหนดพารามิเตอร์แรกเป็นชื่อของหน้าต่างที่ต้องการแสดงภาพและพารามิเตอร์ที่สองเป็นภาพที่ต้องการแสดง ดังตัวอย่างต่อไปนี้

```
cv2.imshow('Webcam', image)
```
ใช้ในการรอรับอินพุตจากแป้นพิมพ์ โดยฟังก์ชัน cv2.waitKey() รอรับอินพุตจากผู้ใช้  เเละใช้ if ตรวจสอบว่าผู้ใช้กดปุ่ม 'q' หรือไม่ ถ้าใช้จะทำการหยุดการทำงานของลูปด้วยคำสั่ง break ซึ่งทำให้โปรแกรมจบการทำงานและปิดหน้าต่างที่แสดงภาพ ตามตัวอย่างต่อไปนี้
```
key = cv2.waitKey(1) & 0xFF
     if key == ord('q'):
        break
```

```
cap.release()
cv2.destroyAllWindows()
```
หลังนั้นใช้คำสั่งปิดการทำงานของโปรแกรมที่ทำงานอยู่เบื้องหลัง
cap.release() ใช้เพื่อปิดการใช้งานทรัพยากรที่ถูกเปิดไว้
cv2.destroyAllWindows() ใช้เพื่อปิดหน้าต่างทั้งหมดที่ถูกเปิดด้วย OpenCV

ผลลัพธ์ที่ได้ 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wcg0w93wd4irharchtnt.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l8jo39u0faee4reu5xb2.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yizvj308x3nig4dwgcyu.png)

## สรุป
จากผลลัพธ์จะแสดงให้มีการตรวจจับวัตถุและติดตาม ใบหน้าโดยจะวาด landmark บนใบหน้าและเลือกที่จับจุดสำคัญบนอวัยวะต่างๆ บนใบหน้าเป็นจุด ๆ เช่น คิ้ว จมูก ปาก ที่เลือกกำหนดเป็นจุดสำคัญ และการวาดมือก็จะทำการเลือกจุดสนใจหรือข้อต่อต่างๆ บนมือและนำมาวาดรวมกับการโพสท่าทางของโครงสร้างร่างกายของมนุษย์ โดยที่จะสังเกตได้ว่า การวาด landmark ใบหน้า แยกกับ การวาด landmark บนมือกับโครงสร้างร่างกาย



## References

> https://github.com/nicknochnack/Full-Body-Estimation-using-Media-Pipe-Holistic/blob/main/Media%20Pipe%20Holistic%20Tutorial.ipynb