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

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

การจัดประเภทท่าทางและการนับซ้ำด้วยอัลกอริทึม 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 ด้านล่างแสดงท่าโยคะ Warrior II มุมโดยประมาณ ที่ระบุท่าทางนี้จะเขียนเป็นภาษา:

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

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

  • มุม 90 องศาที่ไหล่ทั้ง 2 ข้าง
  • 180 องศาที่ข้อศอกทั้ง 2 ข้าง
  • มุม 90 องศาที่ขาด้านหน้าและเอว
  • มุม 180 องศาที่เข่าด้านหลัง
  • มุม 135 องศาที่เอว

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

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

ข้อมูลโค้ดด้านล่างแสดงวิธีใช้พิกัด X และ Y เพื่อคํานวณมุมระหว่างส่วนต่างๆ ของร่างกาย วิธีการจัดประเภทนี้ มีข้อจำกัดบางประการ เมื่อตรวจสอบเฉพาะ 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]];