ตัวเลือกการจัดประเภทท่าทาง

จัดทุกอย่างให้เป็นระเบียบอยู่เสมอด้วยคอลเล็กชัน บันทึกและจัดหมวดหมู่เนื้อหาตามค่ากำหนดของคุณ

ML Kit Pose Detection API ช่วยให้คุณตีความการโพสท่าที่มีความหมายได้โดยตรวจสอบตําแหน่งสัมพัทธ์ของส่วนต่างๆ ของร่างกาย หน้านี้สาธิต ตัวอย่างบางส่วน

การนับตําแหน่งท่าทางและการกล่าวซ้ําด้วยอัลกอริทึม k-NN

หนึ่งในแอปพลิเคชันการตรวจสอบท่าทางที่พบบ่อยที่สุดคือการติดตามการออกกําลังกาย การสร้างตัวแยกประเภทท่าทางที่บันทึกท่าทางและการนับซ้ําของการออกกําลังกายที่เฉพาะเจาะจงอาจเป็นเรื่องยากสําหรับนักพัฒนาซอฟต์แวร์

ในส่วนนี้ เราจะอธิบายวิธีที่เราสร้างตัวแยกประเภทท่าทางที่กําหนดเองโดยใช้ MediaPipe Colab และสาธิตตัวแยกประเภทที่ใช้งานได้ในแอปตัวอย่าง ML Kit

หากคุณไม่คุ้นเคยกับ Google Colaboratory โปรดดูคู่มือแนะนํา

เพื่อจดจําท่าทางเราใช้อัลกอริทึมใกล้เคียงที่สุด k-NN (k-NN) เนื่องจากความเรียบง่ายและเริ่มต้นใช้งานได้ง่าย อัลกอริทึมจะกําหนดคลาสของออบเจ็กต์โดยอิงตามตัวอย่างที่ใกล้เคียงที่สุดในชุดการฝึก

ทําตามขั้นตอนต่อไปนี้เพื่อสร้างและฝึกระบบจดจํา

1. รวบรวมตัวอย่างรูปภาพ

เรารวบรวมตัวอย่างรูปภาพของแบบฝึกหัดแก้ปัญหาจากแหล่งที่มาต่างๆ เราเลือกภาพ 2-3 ร้อยภาพสําหรับการออกกําลังกายแต่ละครั้ง เช่น "up" และ "down" ตําแหน่งสําหรับวิดพื้น การรวบรวมตัวอย่างที่ครอบคลุมมุมกล้อง สภาพสภาพแวดล้อม รูปร่าง และท่าออกกําลังกายต่างๆ เป็นสิ่งสําคัญ

ภาพที่ 1 ท่าโพสท่าขึ้นและลง

2. เรียกใช้การตรวจสอบท่าทางบนตัวอย่างรูปภาพ

ซึ่งจะสร้างชุดท่าทางที่สําคัญสําหรับการฝึก เราไม่สนใจการตรวจหาท่าทางของตัวเองเนื่องจากเราจะฝึกโมเดลของเราเองในขั้นตอนถัดไป

อัลกอริทึม k-NN ที่เราเลือกสําหรับการแยกประเภทท่าทางที่กําหนดเองจําเป็นต้องมีการนําเสนอเวกเตอร์ฟีเจอร์สําหรับตัวอย่างแต่ละรายการ และเมตริกเพื่อคํานวณระยะทางระหว่างเวกเตอร์ 2 เวกเตอร์เพื่อหาเป้าหมายที่ใกล้กับตัวอย่างท่าทางมากที่สุด เราจึงต้องแปลงตําแหน่งของท่าทางที่เราเพิ่งได้รับมา

หากต้องการแปลงจุดสังเกตท่าทางเป็นเวกเตอร์ฟีเจอร์ เราจะใช้ระยะทางแบบคู่กันระหว่างรายการท่าทางที่กําหนดไว้ล่วงหน้า เช่น ระยะห่างระหว่างข้อมือและไหล่ ข้อเท้าและสะโพก และข้อมือซ้ายและขวา เนื่องจากขนาดของรูปภาพ อาจแตกต่างกัน เราจึงปรับท่าทางให้มีขนาดลําตัวเท่ากันและจัดแนวตามร่างกายในแนวตั้งก่อนแปลงจุดสังเกต

3. ฝึกโมเดลและนับจํานวนการทําซ้ํา

เราใช้ MediaPipe Colab เพื่อเข้าถึงโค้ดสําหรับตัวแยกประเภทและฝึกโมเดลอีกครั้ง

เราใช้อัลกอริทึม Colab อีกรายการหนึ่งในการตรวจดูการกล่าวซ้ําๆ เพื่อตรวจสอบความน่าจะเป็นของอันดับเป้าหมาย เช่น

  • เมื่อความน่าจะเป็นของ "down" คลาสท่าทางผ่านเกณฑ์ที่ระบุเป็นครั้งแรก อัลกอริทึมจะทําเครื่องหมายว่าป้อน "down" คลาสท่าทาง
  • เมื่อความน่าจะเป็นลดลงต่ํากว่าเกณฑ์ อัลกอริทึมจะทําเครื่องหมายว่า "down" คลาสท่าทางออกจาก และเพิ่มตัวนับ
ภาพที่ 2 ตัวอย่างการนับซ้ํา

4. ผสานรวมกับแอปการเริ่มต้นใช้งานด่วนของ ML Kit

Colab ข้างต้นจะสร้างไฟล์ CSV ที่คุณป้อนข้อมูลกับตัวอย่างท่าทางทั้งหมดของคุณได้ ในส่วนนี้ คุณจะได้ทราบวิธีผสานรวมไฟล์ CSV เข้ากับแอป Quickstart สําหรับ Android ของ ML Kit เพื่อดูการจัดประเภทท่าทางที่กําหนดเองแบบเรียลไทม์

ลองใช้ท่าทางกับตัวอย่างที่รวมอยู่ในแอปเริ่มต้นอย่างรวดเร็ว

  • ดาวน์โหลดโปรเจ็กต์แอป Quick Start สําหรับ Android ที่ใช้ ML Kit จาก GitHub และตรวจสอบว่าบิลด์นั้นทํางานได้ดี
  • ไปที่ LivePreviewActivity และเปิดใช้การตรวจจับท่าทาง Run classification จากหน้าการตั้งค่า #39 แต่ตอนนี้คุณควรจะแยกประเภทรายการวิดพื้นและการสควอทได้แล้ว

เพิ่ม CSV ของคุณเอง

  • เพิ่มไฟล์ CSV ไปยังโฟลเดอร์ชิ้นงานของแอป
  • ใน PoseClassifierProcessor ให้อัปเดตตัวแปร POSE_SAMPLES_FILE และ POSE_CLASSES ให้ตรงกับไฟล์ CSV และตัวอย่าง
  • สร้างและเรียกใช้แอป

โปรดทราบว่าการจัดประเภทอาจทํางานได้ไม่ดีหากมีตัวอย่างไม่เพียงพอ โดยทั่วไป ต้องมีตัวอย่างประมาณ 100 ชิ้นต่อชั้นเรียน

ดูข้อมูลเพิ่มเติมและลองใช้งานด้วยตนเองได้ที่ MediaPipe Colab และคู่มือการแยกประเภท MediaPipe

จดจําท่าทางสัมผัสง่ายๆ ด้วยการคํานวณระยะทางของจุดสังเกต

เมื่อจุดสังเกตอย่างน้อย 2 แห่งอยู่ใกล้กัน ก็จะใช้การจดจําท่าทางสัมผัสได้ ตัวอย่างเช่น เมื่อจุดสังเกตสําหรับนิ้วอย่างน้อย 1 นิ้วอยู่ในมือนั้นใกล้เคียงกับจุดสังเกตสําหรับจมูก คุณสามารถอนุมานผู้ใช้ว่าใบหน้าส่วนใหญ่สัมผัสได้

ภาพที่ 3 การตีความท่าทาง

จดจําท่าโยคะด้วยการเรียนรู้ของระบบมุม

คุณจะแสดงท่าโยคะได้โดยการคํานวณมุมของข้อต่อต่างๆ เช่น รูปที่ 2 ด้านล่างนี้แสดงท่าโยคะนักรบ II มุมโดยประมาณ ที่ใช้ระบุตําแหน่งนี้คือ

ภาพที่ 4 โพสท่าทํามุมมุม

การโพสท่านี้อธิบายได้ว่าเป็นการรวมมุมร่างกายโดยประมาณดังต่อไปนี้

  • มุม 90 องศาที่ไหล่ทั้ง 2 ข้าง
  • 180 องศาที่ข้อศอกทั้งสอง
  • มุม 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]];