Opsi klasifikasi pose

Dengan ML Kit Pose Detection API, Anda dapat memperoleh interpretasi yang bermakna tentang pose dengan memeriksa posisi relatif berbagai bagian tubuh. Halaman ini menunjukkan beberapa contoh.

Klasifikasi pose dan penghitungan pengulangan dengan algoritma k-NN

Salah satu aplikasi deteksi pose yang paling umum adalah pelacakan kebugaran. Membuat pengklasifikasi pose yang mengenali pose kebugaran tertentu dan menghitung repetisi dapat menjadi tantangan bagi developer.

Di bagian ini, kami menjelaskan cara membuat pengklasifikasi postur kustom menggunakan MediaPipe Colab, dan menunjukkan pengklasifikasi yang berfungsi di aplikasi contoh ML Kit kami.

Jika Anda tidak terbiasa dengan Google Colaboratory, lihat panduan pengantar.

Untuk mengenali pose, kita menggunakan algoritma k-nearest neighbors (k-NN) karena sederhana dan mudah digunakan. Algoritma menentukan class objek berdasarkan sampel terdekat dalam set pelatihan.

Ikuti langkah-langkah berikut untuk mem-build dan melatih pengenal:

1. Mengumpulkan contoh gambar

Kami mengumpulkan sampel gambar latihan target dari berbagai sumber. Rab memilih beberapa ratus gambar untuk setiap latihan, seperti "naik" dan "down" posisi untuk push-up. Penting untuk mengumpulkan sampel yang mencakup berbagai sudut kamera, kondisi lingkungan, bentuk tubuh, dan variasi olahraga.

Gambar 1. Posisi pose pushup naik dan turun

2. Menjalankan deteksi pose pada gambar sampel

Hal ini menghasilkan serangkaian penanda pose yang akan digunakan untuk pelatihan. Kami tidak tertarik pada deteksi pose itu sendiri, karena kita akan melatih model Anda sendiri di langkah berikutnya.

Algoritma k-NN yang dipilih untuk klasifikasi pose kustom membutuhkan representasi vektor fitur untuk setiap sampel dan metrik yang akan dihitung jarak antara dua vektor untuk menemukan target yang paling dekat dengan sampel pose. Artinya, kita harus mengonversi penanda pose yang baru saja kita dapatkan.

Untuk mengonversi penanda pose menjadi vektor fitur, kita menggunakan jarak berpasangan antara daftar sendi pose yang telah ditentukan sebelumnya, seperti jarak antara pergelangan tangan dan bahu, pergelangan kaki dan pinggul, serta pergelangan tangan kiri dan kanan. Karena skala gambar dapat bervariasi, kami menormalisasi pose agar memiliki ukuran torso dan orientasi torso vertikal yang sama sebelum mengonversi penanda.

3. Melatih model dan menghitung pengulangan

Kami menggunakan MediaPipe Colab untuk mengakses kode untuk pengklasifikasi dan melatih model.

Untuk menghitung pengulangan, kami menggunakan algoritma Colab lain untuk memantau nilai minimum probabilitas posisi pose target. Contoh:

  • Saat probabilitas class pose "down" melewati nilai minimum tertentu untuk pertama kalinya, algoritma akan menandai bahwa class pose "down" dimasukkan.
  • Saat probabilitas turun di bawah nilai minimum, algoritma akan menandai bahwa class pose "down" telah keluar dan meningkatkan penghitung.
Gambar 2. Contoh penghitungan pengulangan

4. Mengintegrasikan dengan aplikasi panduan memulai ML Kit

Colab di atas menghasilkan file CSV yang dapat Anda isi dengan semua contoh pose. Di bagian ini, Anda akan mempelajari cara mengintegrasikan {i>file<i} CSV Anda dengan Aplikasi panduan memulai Android ML Kit untuk melihat klasifikasi pose kustom secara real time.

Mencoba klasifikasi pose dengan contoh yang dipaketkan dalam aplikasi memulai cepat

  • Dapatkan project aplikasi panduan memulai Android ML Kit dari GitHub dan pastikan project tersebut dibuat dan berjalan dengan baik.
  • Buka LivePreviewActivity dan aktifkan Deteksi Pose Run classification dari menu Setelan' kami. Sekarang Anda seharusnya dapat mengklasifikasikan gerakan pushup dan squat.

Menambahkan CSV Anda sendiri

  • Tambahkan file CSV ke folder aset aplikasi.
  • Di PoseClassifierProcessor, perbarui variabel POSE_SAMPLES_FILE dan POSE_CLASSES agar sesuai dengan file CSV dan contoh posenya.
  • Bangun dan jalankan aplikasi.

Perhatikan bahwa klasifikasi mungkin tidak berfungsi dengan baik jika tidak ada cukup sampel. Biasanya, Anda memerlukan sekitar 100 sampel per class pose.

Untuk mempelajari lebih lanjut dan mencobanya sendiri, lihat MediaPipe Colab dan panduan klasifikasi MediaPipe.

Mengenali gestur sederhana dengan menghitung jarak penanda

Jika dua atau beberapa penanda berada berdekatan, penanda tersebut dapat digunakan untuk mengenali gestur. Misalnya, saat penanda untuk satu atau beberapa jari pada tangan dekat dengan tonggak batas untuk hidung, Anda dapat menyimpulkan bahwa pengguna paling yang menyentuh wajah mereka.

Gambar 3. Menafsirkan pose

Mengenali pose yoga dengan heuristik sudut

Anda dapat mengidentifikasi pose yoga dengan menghitung sudut berbagai sendi. Sebagai gambar 2 di bawah ini menunjukkan pose yoga Warrior II. Perkiraan sudut yang mengidentifikasi pose ini ditulis dalam:

Gambar 4. Membagi pose menjadi beberapa sudut

Pose ini dapat dijelaskan sebagai kombinasi perkiraan sudut bagian tubuh berikut:

  • Sudut 90 derajat di kedua bahu
  • 180 derajat di kedua siku
  • Sudut 90 derajat di kaki depan dan pinggang
  • Sudut 180 derajat di lutut belakang
  • Sudut 135 derajat di pinggang

Anda dapat menggunakan penanda pose untuk menghitung sudut-sudut ini. Misalnya, sudut di kaki depan kanan dan pinggang adalah sudut antara garis dari bahu kanan ke pinggul kanan, dan garis dari pinggul kanan ke lutut kanan.

Setelah menghitung semua sudut yang diperlukan untuk mengidentifikasi pose, Anda dapat memeriksa untuk melihat apakah ada kecocokan, dalam hal ini Anda telah mengenali pose.

Cuplikan kode di bawah menunjukkan cara menggunakan koordinat X dan Y untuk menghitung sudut antara dua bagian tubuh. Pendekatan klasifikasi ini memiliki beberapa batasan. Dengan hanya memeriksa X dan Y, sudut yang dihitung akan bervariasi sesuai dengan sudut antara subjek dan kamera. Anda akan mendapatkan hasil terbaik dengan gambar yang lurus, lurus ke depan. Anda juga dapat mencoba memperluas algoritma ini dengan menggunakan koordinat Z dan melihat apakah algoritma ini berperforma lebih baik untuk kasus penggunaan Anda.

Menghitung sudut penanda di Android

Metode berikut menghitung sudut antara tiga penanda apa pun. Cara ini memastikan sudut yang dikembalikan berada di antara 0 dan 180 derajat.

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;
}

Berikut cara menghitung sudut pada pinggul kanan:

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));

Menghitung sudut terkenal di iOS

Metode berikut menghitung sudut antara tiga penanda apa pun. Cara ini memastikan sudut yang dikembalikan berada di antara 0 dan 180 derajat.

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;
}

Berikut cara menghitung sudut di pinggul kanan:

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]];