เมื่อใช้ ML Kit Pose Detection API คุณจะได้รับการตีความที่มีความหมาย ด้วยการตรวจสอบตำแหน่งสัมพัทธ์ของส่วนต่างๆ ของร่างกาย หน้านี้ จะแสดงให้เห็นตัวอย่าง 2-3 ข้อ
การจัดประเภทท่าทางและการนับซ้ำด้วยอัลกอริทึม k-NN
หนึ่งในการใช้งานที่พบบ่อยที่สุดของการตรวจจับท่าทางคือการติดตามการออกกำลังกาย การสร้างตัวแยกประเภทท่าทางที่จดจำท่าทางและจำนวนการออกกำลังกายที่เจาะจง การทำซ้ำๆ อาจเป็นสิ่งที่ท้าทายสำหรับนักพัฒนาซอฟต์แวร์
ในส่วนนี้ เราจะอธิบายวิธีที่เราสร้างท่าทางที่กำหนดเอง ตัวแยกประเภทที่ใช้ MediaPipe Colab และ แสดงตัวแยกประเภทที่ใช้งานได้ในแอปตัวอย่าง ML Kit ของเรา
หากคุณไม่คุ้นเคยกับ Google Colaboratory โปรดดูที่ คู่มือแนะนำ
เราใช้อัลกอริทึม k-Nabor Nabors (k-NN) ในการจดจำท่าทางเพราะว่านั้นง่ายมาก และเริ่มต้นได้ง่าย อัลกอริทึมจะกำหนดคลาสของออบเจ็กต์ตาม ตัวอย่างที่ใกล้เคียงที่สุดในชุดการฝึก
ทำตามขั้นตอนต่อไปนี้เพื่อสร้างและฝึกโปรแกรมรู้จำ
1. รวบรวมตัวอย่างรูปภาพ
เราได้รวบรวมตัวอย่างรูปภาพของแบบฝึกหัดเป้าหมายจากแหล่งที่มาต่างๆ พ เลือกรูปภาพสองสามร้อยภาพสำหรับการออกกำลังกายแต่ละครั้ง เช่น "ขึ้น" และ "ลง" ตำแหน่ง สำหรับการวิดพื้น คุณต้องรวบรวมตัวอย่างที่ครอบคลุมกล้องหลายตัว มุม สภาพสภาพแวดล้อม รูปร่าง และรูปแบบการออกกำลังกายที่หลากหลาย
2. เรียกใช้การตรวจหาท่าทางในรูปภาพตัวอย่าง
การดำเนินการนี้จะสร้างชุดจุดสังเกตของท่าทางที่ใช้สำหรับการฝึก เราไม่ ความสนใจในการตรวจจับท่าทาง เนื่องจากเราจะฝึก ของโมเดลของตัวเองในขั้นตอนถัดไป
อัลกอริทึม k-NN ที่เราเลือกสำหรับการจัดประเภทท่าทางที่กำหนดเองจะต้องใช้ แสดงเวกเตอร์ของตัวอย่างแต่ละรายการและเมตริกที่จะคำนวณ ระยะทางระหว่างเวกเตอร์ 2 เวกเตอร์เพื่อหาเป้าหมายที่อยู่ใกล้กับตัวอย่างท่าทางมากที่สุด ซึ่งหมายความว่าเราต้องแปลงจุดสังเกตต่างๆ ที่เราเพิ่งได้มา
ในการแปลงจุดสังเกตของการโพสจะเป็นเวกเตอร์ของจุดสนใจ เราใช้ระยะทางแบบคู่ ระหว่างรายการของข้อต่อโพสที่กำหนดไว้ล่วงหน้า เช่น ระยะห่างระหว่างข้อมือกับ ไหล่ ข้อเท้าและสะโพก และข้อมือซ้ายและขวา เนื่องจากขนาดของรูปภาพ มีความหลากหลาย โดยปรับท่าทางต่างๆ ให้เป็นมาตรฐานเพื่อให้มีขนาดลำตัวและลำตัวในแนวดิ่งเท่ากัน การวางแนวก่อนที่จะแปลงจุดสังเกต
3. ฝึกโมเดลและนับการทำซ้ำ
เราใช้ MediaPipe Colab เพื่อเข้าถึงโค้ดสำหรับตัวแยกประเภทและ ฝึกโมเดล
ในการนับการเกิดซ้ำ เราใช้อัลกอริทึมของ Colab อีกตัวหนึ่งเพื่อตรวจสอบความน่าจะเป็น ของตำแหน่งเป้าหมาย เช่น
- เมื่อความน่าจะเป็นของการ "ลดลง" ทำให้คลาสผ่านเกณฑ์ที่กำหนดให้สำหรับ ในครั้งแรก อัลกอริทึมจะทำเครื่องหมาย "ลูกศรลง" มีการป้อนคลาสการโพส
- เมื่อความน่าจะเป็นลดลงต่ำกว่าเกณฑ์ อัลกอริทึมจะทำเครื่องหมาย "ลง" ออกจากคลาสการโพสแล้วและเพิ่มตัวนับ
4. ผสานรวมกับแอปเริ่มต้นใช้งาน ML Kit อย่างรวดเร็ว
Colab ด้านบนจะสร้างไฟล์ CSV ที่คุณป้อนข้อมูลท่าทางทั้งหมดได้ ตัวอย่าง ในหัวข้อนี้ คุณจะได้เรียนรู้วิธีผสานรวมไฟล์ CSV กับ แอปเริ่มต้นใช้งาน ML Kit อย่างรวดเร็วของ Android เพื่อดูการจัดประเภทท่าทางที่กำหนดเองแบบเรียลไทม์
ลองใช้การแยกประเภทท่าทางด้วยตัวอย่างที่รวมอยู่ในแอปการเริ่มต้นอย่างรวดเร็ว
- รับโปรเจ็กต์แอปเริ่มต้นอย่างรวดเร็วสำหรับ Android ของ ML Kit จาก GitHub และตรวจสอบว่าสร้างและทำงานได้ดี
- ไปที่
LivePreviewActivity
และเปิดใช้การตรวจหาท่าทางRun classification
จากแท็บ "การตั้งค่า" ตอนนี้คุณควรแยกประเภทการวิดพื้นและสควอทได้แล้ว
เพิ่มไฟล์ CSV ของคุณเอง
- เพิ่มไฟล์ CSV ลงในโฟลเดอร์เนื้อหาของแอป
- ใน PoseClassifierProcessor
อัปเดตตัวแปร
POSE_SAMPLES_FILE
และPOSE_CLASSES
ให้ตรงกับ CSV และตัวอย่างท่าทาง - สร้างและเรียกใช้แอป
โปรดทราบว่าการแยกประเภทอาจทำงานได้ไม่ดีหากมีตัวอย่างไม่เพียงพอ โดยทั่วไปแล้วคุณจำเป็นต้องใช้ตัวอย่างประมาณ 100 ตัวอย่างต่อคลาสท่าทาง
หากต้องการดูข้อมูลเพิ่มเติมและลองใช้งานด้วยตัวเอง ให้ไปที่ MediaPipe Colab และคู่มือการแยกประเภท MediaPipe
การจดจำท่าทางสัมผัสง่ายๆ โดยการคำนวณระยะห่างของจุดสังเกต
เมื่อจุดสังเกตตั้งแต่ 2 รายการขึ้นไปอยู่ใกล้กัน สามารถใช้เพื่อ จดจำท่าทางสัมผัส ตัวอย่างเช่น เมื่อจุดสังเกตสำหรับ 1 นิ้วขึ้นไปบน มืออยู่ใกล้กับจุดสังเกตของจมูก คุณสามารถอนุมานว่าผู้ใช้คนส่วนใหญ่เป็น ที่มีแนวโน้มว่าจะสัมผัสใบหน้าของเด็กๆ
การจดจำท่าโยคะด้วยการเรียนรู้จากมุม
คุณสามารถหาท่าโยคะได้ด้วยการคำนวณมุมของข้อต่อต่างๆ สำหรับ ตัวอย่างเช่น รูปที่ 2 ด้านล่างแสดงท่าโยคะของนักรบ II มุมโดยประมาณ ที่ระบุท่าทางนี้จะเขียนเป็นภาษา:
ท่านี้สามารถอธิบายได้ว่าเป็นการผสมระหว่างร่างกายโดยประมาณดังต่อไปนี้ มุมของชิ้นส่วน:
- มุม 90 องศาที่ไหล่ทั้ง 2 ข้าง
- 180 องศาที่ข้อศอกทั้ง 2 ข้าง
- ทำมุม 90 องศาที่ขาหน้าและเอว
- มุม 180 องศาที่เข่าด้านหลัง
- มุม 135 องศาที่เอว
คุณสามารถใช้จุดสังเกตในการโพสเพื่อคำนวณมุมเหล่านี้ได้ ตัวอย่างเช่น มุม ที่ขาหน้าและเอวด้านขวาคือมุมระหว่างเส้นจากด้านขวา หัวไหล่ไปจนถึงสะโพกขวา และเส้นจากสะโพกขวาถึงหัวเข่าขวา
เมื่อคำนวณทุกมุมที่ต้องการระบุท่าทางแล้ว คุณจะตรวจสอบได้ว่า เพื่อดูว่ามีคำที่ตรงกันหรือไม่ ซึ่งในกรณีนี้คุณก็จำท่าทางเหล่านั้นได้
ข้อมูลโค้ดด้านล่างแสดงวิธีใช้พิกัด X และ Y เพื่อ คำนวณมุมระหว่างส่วนของร่างกาย 2 ส่วน วิธีการจัดประเภทนี้ มีข้อจำกัดบางประการ เมื่อตรวจสอบเฉพาะ X และ Y มุมที่คำนวณได้จะแตกต่างกันไป ตามมุมระหว่างวัตถุและกล้อง คุณจะได้รับ จะได้ผลลัพธ์ที่ดีที่สุดด้วยรูปภาพที่ตรงไปตรงมา ตรงไปตรงมา และอยู่บนศีรษะ นอกจากนี้คุณยัง ขยายอัลกอริทึมนี้ด้วยการใช้ พิกัด Z เพื่อดูว่าจะทำงานได้ดีขึ้นสำหรับกรณีการใช้งานของคุณไหม
การประมวลผลมุมจุดสังเกตบน Android
วิธีการต่อไปนี้จะคำนวณมุมระหว่าง 3 ประเภท จุดสังเกต เพื่อให้แน่ใจว่ามุมที่แสดงผลอยู่ระหว่าง 0 และ 180 องศา
Kotlin
fun getAngle(firstPoint: PoseLandmark, midPoint: PoseLandmark, lastPoint: PoseLandmark): Double { var result = Math.toDegrees(atan2(lastPoint.getPosition().y - midPoint.getPosition().y, lastPoint.getPosition().x - midPoint.getPosition().x) - atan2(firstPoint.getPosition().y - midPoint.getPosition().y, firstPoint.getPosition().x - midPoint.getPosition().x)) result = Math.abs(result) // Angle should never be negative if (result > 180) { result = 360.0 - result // Always get the acute representation of the angle } return result }
Java
static double getAngle(PoseLandmark firstPoint, PoseLandmark midPoint, PoseLandmark lastPoint) { double result = Math.toDegrees( atan2(lastPoint.getPosition().y - midPoint.getPosition().y, lastPoint.getPosition().x - midPoint.getPosition().x) - atan2(firstPoint.getPosition().y - midPoint.getPosition().y, firstPoint.getPosition().x - midPoint.getPosition().x)); result = Math.abs(result); // Angle should never be negative if (result > 180) { result = (360.0 - result); // Always get the acute representation of the angle } return result; }
วิธีคํานวณมุมที่สะโพกด้านขวา
Kotlin
val rightHipAngle = getAngle( pose.getPoseLandmark(PoseLandmark.Type.RIGHT_SHOULDER), pose.getPoseLandmark(PoseLandmark.Type.RIGHT_HIP), pose.getPoseLandmark(PoseLandmark.Type.RIGHT_KNEE))
Java
double rightHipAngle = getAngle( pose.getPoseLandmark(PoseLandmark.Type.RIGHT_SHOULDER), pose.getPoseLandmark(PoseLandmark.Type.RIGHT_HIP), pose.getPoseLandmark(PoseLandmark.Type.RIGHT_KNEE));
การประมวลผลมุมจุดสังเกตบน iOS
วิธีการต่อไปนี้จะคำนวณมุมระหว่าง 3 ประเภท จุดสังเกต เพื่อให้แน่ใจว่ามุมที่แสดงผลอยู่ระหว่าง 0 และ 180 องศา
Swift
func angle( firstLandmark: PoseLandmark, midLandmark: PoseLandmark, lastLandmark: PoseLandmark ) -> CGFloat { let radians: CGFloat = atan2(lastLandmark.position.y - midLandmark.position.y, lastLandmark.position.x - midLandmark.position.x) - atan2(firstLandmark.position.y - midLandmark.position.y, firstLandmark.position.x - midLandmark.position.x) var degrees = radians * 180.0 / .pi degrees = abs(degrees) // Angle should never be negative if degrees > 180.0 { degrees = 360.0 - degrees // Always get the acute representation of the angle } return degrees }
Objective-C
(CGFloat)angleFromFirstLandmark:(MLKPoseLandmark *)firstLandmark midLandmark:(MLKPoseLandmark *)midLandmark lastLandmark:(MLKPoseLandmark *)lastLandmark { CGFloat radians = atan2(lastLandmark.position.y - midLandmark.position.y, lastLandmark.position.x - midLandmark.position.x) - atan2(firstLandmark.position.y - midLandmark.position.y, firstLandmark.position.x - midLandmark.position.x); CGFloat degrees = radians * 180.0 / M_PI; degrees = fabs(degrees); // Angle should never be negative if (degrees > 180.0) { degrees = 360.0 - degrees; // Always get the acute representation of the angle } return degrees; }
วิธีคํานวณมุมที่สะโพกด้านขวา
Swift
let rightHipAngle = angle( firstLandmark: pose.landmark(ofType: .rightShoulder), midLandmark: pose.landmark(ofType: .rightHip), lastLandmark: pose.landmark(ofType: .rightKnee))
Objective-C
CGFloat rightHipAngle = [self angleFromFirstLandmark:[pose landmarkOfType:MLKPoseLandmarkTypeRightShoulder] midLandmark:[pose landmarkOfType:MLKPoseLandmarkTypeRightHip] lastLandmark:[pose landmarkOfType:MLKPoseLandmarkTypeRightKnee]];