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

เมื่อใช้ ML Kit Pose Detection API คุณจะได้รับการตีความที่มีความหมาย ด้วยการตรวจสอบตำแหน่งสัมพัทธ์ของส่วนต่างๆ ของร่างกาย หน้านี้ จะแสดงให้เห็นตัวอย่าง 2-3 ข้อ

การจัดประเภทท่าทางและการนับซ้ำด้วยอัลกอริทึม k-NN

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

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

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

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

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

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

เราได้รวบรวมตัวอย่างรูปภาพของแบบฝึกหัดเป้าหมายจากแหล่งที่มาต่างๆ พ เลือกรูปภาพสองสามร้อยภาพสำหรับการออกกำลังกายแต่ละครั้ง เช่น "ขึ้น" และ "ลง" ตำแหน่ง สำหรับการวิดพื้น คุณต้องรวบรวมตัวอย่างที่ครอบคลุมกล้องหลายตัว มุม สภาพสภาพแวดล้อม รูปร่าง และรูปแบบการออกกำลังกายที่หลากหลาย

รูปที่ 1. ท่าวิดพื้นแบบขึ้นและลง

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

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

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

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

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

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

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

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

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

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

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

เพิ่มไฟล์ CSV ของคุณเอง

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

โปรดทราบว่าการแยกประเภทอาจทำงานได้ไม่ดีหากมีตัวอย่างไม่เพียงพอ โดยทั่วไปแล้วคุณจำเป็นต้องใช้ตัวอย่างประมาณ 100 ตัวอย่างต่อคลาสท่าทาง

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

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

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

รูปที่ 3 การตีความท่าทาง

การจดจำท่าโยคะด้วยการเรียนรู้จากมุม

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

รูปที่ 4 โพสท่าให้เป็นมุมต่างๆ

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

  • มุม 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]];