Poz sınıflandırma seçenekleri

ML Kit Pose Detection API ile vücudun çeşitli bölümlerinin göreli konumlarını kontrol ederek pozlarla ilgili anlamlı yorumlar elde edebilirsiniz. Bu sayfada birkaç örnek gösterilmektedir.

k-NN algoritmasıyla pozisyon sınıflandırması ve tekrar sayma

Poz algılamanın en yaygın uygulamalarından biri fitness takibidir. Belirli fitness duruşlarını tanıyan ve tekrarları sayan bir poz sınıflandırıcı oluşturmak, geliştiriciler için zor bir başarı olabilir.

Bu bölümde, MediaPipe Colab'i kullanarak nasıl özel poz sınıflandırıcı oluşturduğumuz ve ML Kiti örnek uygulamamızda çalışan bir sınıflandırıcıyı nasıl gösterdiğimiz açıklanmaktadır.

Google Colaboratory'yi bilmiyorsanız lütfen tanıtım kılavuzuna göz atın.

Pozları tanımak için k-en yakın komşu algoritmasını (k-NN) kullanırız çünkü bu algoritma basit ve başlangıçta yapılması kolaydır. Algoritma, eğitim kümesindeki en yakın örneklere bağlı olarak nesnenin sınıfını belirler.

Tanıyıcı oluşturmak ve eğitmek için şu adımları uygulayın:

1. Görüntü örneklerini topla

Hedef egzersizlerin resim örneklerini çeşitli kaynaklardan topladık. Her egzersiz için birkaç yüz resim seçtik. Örneğin, şınav için "yukarı" ve "aşağı" pozisyonları seçtik. Farklı kamera açılarını, ortam koşullarını, vücut şekillerini ve egzersiz varyasyonlarını kapsayan örnekler toplamak önemlidir.

Şekil 1. Yukarı ve aşağı şınav pozu pozisyonları

2. Örnek resimlerde poz algılamayı çalıştırın

Bu, eğitim için kullanılacak bir dizi poz önemli noktası oluşturur. Bir sonraki adımda kendi modelimizi eğiteceğimiz için poz algılamanın kendisi ilgimizi çekmiyor.

Özel poz sınıflandırması için seçtiğimiz k-NN algoritmasında, poz örneğine en yakın hedefi bulmak amacıyla her örnek için bir özellik vektörü temsili ve iki vektör arasındaki mesafeyi hesaplamak üzere bir metrik gerekir. Bu, yeni elde ettiğimiz poz yer işaretlerini dönüştürmemiz gerektiği anlamına gelir.

Poz önemli noktalarını özellik vektörüne dönüştürmek için, önceden tanımlanmış poz eklem listeleri arasındaki ikili mesafeleri (ör. bilek ile omuz, ayak bileği ve kalça ile sol ve sağ bilekler arasındaki mesafe) kullanırız. Resimlerin ölçeği değişebileceğinden, önemli noktaları dönüştürmeden önce duruşları aynı gövde boyutuna ve dikey gövde yönüne sahip olacak şekilde normalleştirdik.

3. Modeli eğitin ve tekrarları say

Sınıflandırıcının koduna erişmek ve modeli eğitmek için MediaPipe Colab'i kullandık.

Tekrarları saymak için bir hedef poz konumunun olasılık eşiğini izlemek amacıyla başka bir Colab algoritması kullandık. Örneğin:

  • "Aşağı" poz sınıfının olasılığı belirli bir eşiği ilk kez geçtiğinde, algoritma "aşağı" poz sınıfının girildiğini işaretler.
  • Olasılık eşiğin altına düştüğünde algoritma "aşağı" poz sınıfından çıkıldığını işaretler ve sayacı artırır.
Şekil 2. Tekrar sayımı örneği

4. ML Kit hızlı başlangıç uygulamasıyla entegrasyon

Yukarıdaki Colab, tüm poz örneklerinizle doldurabileceğiniz bir CSV dosyası oluşturur. Bu bölümde, özel poz sınıflandırmasını gerçek zamanlı olarak görmek için CSV dosyanızı ML Kit Android hızlı başlangıç uygulamasıyla nasıl entegre edeceğinizi öğreneceksiniz.

Hızlı başlangıç uygulamasında paket halinde sunulan örneklerle poz sınıflandırmasını deneyin

  • GitHub'dan ML Kit Android hızlı başlangıç uygulaması projesini alarak iyi bir şekilde oluşturulduğundan ve çalıştığından emin olun.
  • LivePreviewActivity uygulamasına gidip Ayarlar sayfasından Pozlama Algılama'yı Run classification etkinleştirin. Artık şınavları ve çömelmeleri sınıflandırabiliyor olmalısınız.

Kendi CSV'nizi ekleyin

  • CSV dosyanızı uygulamanın öğe klasörüne ekleyin.
  • PoseClassifierProcessor'da POSE_SAMPLES_FILE ve POSE_CLASSES değişkenlerini, CSV dosyanızla ve poz örneklerinizle eşleşecek şekilde güncelleyin.
  • Uygulamayı derleyip çalıştırın.

Yeterli örnek yoksa sınıflandırmanın iyi çalışmayabileceğini unutmayın. Genellikle, poz sınıfı başına yaklaşık 100 örneğe ihtiyacınız olur.

Daha fazla bilgi edinmek ve bunu kendiniz denemek için MediaPipe Colab ve MediaPipe sınıflandırma kılavuzuna göz atın.

Önemli nokta mesafesini hesaplayarak basit hareketleri tanıma

İki veya daha fazla önemli nokta birbirine yakın olduğunda, bunlar hareketleri tanımak için kullanılabilir. Örneğin, bir eldeki bir veya daha fazla parmağın yer işareti, burna ilişkin yer işaretine yakın olduğunda, kullanıcının büyük olasılıkla yüzüne dokunduğunu tahmin edebilirsiniz.

Şekil 3. Bir pozu yorumlama

Açı buluşsal yöntemleriyle yoga duruşunu tanıma

Bir yoga duruşunu, çeşitli eklemlerin açılarını hesaplayarak tanımlayabilirsiniz. Örneğin, aşağıdaki Şekil 2'de, Savaşçı II'nin yoga duruşu gösterilmektedir. Bu pozu tanımlayan yaklaşık açılar şu şekilde yazılır:

Şekil 4. Bir pozu açılara ayırma

Bu poz, vücudun belirli kısımlarıyla ilgili yaklaşık açıların aşağıdaki kombinasyonu olarak tanımlanabilir:

  • Her iki omuzda 90 derecelik açı
  • Her iki dirsekte 180 derece
  • Ön bacak ve belde 90 derecelik açı
  • Arka dizinde 180 derecelik açı
  • Belde 135 derecelik açı

Bu açıları hesaplamak için poz yer işaretlerini kullanabilirsiniz. Örneğin, sağ ön bacakla beldeki açı, sağ omuzdan sağ kalçaya doğru çizgi ile sağ kalçadan sağ diziye doğru olan çizgi arasındaki açıdır.

Pozu tanımlamak için gereken tüm açıları hesapladıktan sonra eşleşme olup olmadığını kontrol edebilirsiniz. Bu durumda pozu tanımış olursunuz.

Aşağıdaki kod snippet'i, iki gövde bölümü arasındaki açıyı hesaplamak için X ve Y koordinatlarının nasıl kullanılacağını göstermektedir. Bu sınıflandırma yaklaşımında bazı sınırlamalar vardır. Yalnızca X ve Y düğmelerini işaretlediğinizde, hesaplanan açılar nesne ile kamera arasındaki açıya göre değişir. En iyi sonuçları düz, düz ve doğrudan bir resimle alırsınız. Ayrıca Z koordinatından yararlanarak bu algoritmayı genişletmeyi deneyebilir ve kullanım alanınızda daha iyi performans gösterip göstermediğine bakabilirsiniz.

Android'de önemli nokta açılarını hesaplama

Aşağıdaki yöntem herhangi üç önemli nokta arasındaki açıyı hesaplar. Döndürülen açının 0 ile 180 derece arasında olmasını sağlar.

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

Sağ kalçadaki açı şu şekilde hesaplanabilir:

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'te önemli nokta açılarını hesaplama

Aşağıdaki yöntem herhangi üç önemli nokta arasındaki açıyı hesaplar. Döndürülen açının 0 ile 180 derece arasında olmasını sağlar.

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

Sağ kalçadaki açı şu şekilde hesaplanabilir:

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