ML Kit Pose Detection API로 의미 있는 해석을 도출할 수 있습니다. 다양한 신체 부위의 상대적 위치를 확인하여 포즈의 변화를 파악할 수 있습니다. 이 페이지 몇 가지 예를 보여줍니다.
k-NN 알고리즘을 사용한 포즈 분류 및 반복 횟수 계산
자세 감지의 가장 일반적인 응용 분야 중 하나는 피트니스 추적입니다. 특정 피트니스 자세와 개수를 인식하는 포즈 분류기 빌드 반복은 개발자에게 어려운 작업이 될 수 있습니다.
이 섹션에서는 맞춤 포즈를 만드는 방법을 설명합니다. MediaPipe Colab을 사용한 분류기 는 ML Kit 샘플 앱에서 작동하는 분류기를 보여줍니다.
Google Colaboratory에 익숙하지 않은 경우 소개 가이드를 참조하세요.
포즈를 인식하기 위해 k-최근접 이웃 알고리즘 (k-NN)을 사용합니다. 왜냐하면 간단하게 할 수 있기 때문입니다. 쉽게 시작할 수 있습니다 알고리즘은 이미지에 포함된 가장 가까운 샘플을 볼 수 있습니다.
인식기를 빌드하고 학습시키려면 다음 단계를 따르세요.
1. 이미지 샘플 수집
다양한 출처에서 목표 운동의 이미지 샘플을 수집했습니다. 각 운동에 대해 '업'과 같은 이미지를 몇백 개 선택함 'down' 게재순위 팔 굽혀펴기용. 다양한 카메라를 덮는 샘플을 수집하는 것이 중요합니다. 체형, 운동 변화 등 다양한 건강지표가 포함됩니다.
![](https://developers.google.cn/static/ml-kit/images/vision/pose-detection/terminal_pose.png?authuser=0000&hl=ko)
2. 샘플 이미지에서 포즈 감지 실행
그러면 학습에 사용할 포즈 랜드마크 세트가 생성됩니다. Google은 이 실습에서 배운 내용을 학습하게 될 것이므로 살펴보겠습니다
맞춤 자세 분류를 위해 선택한 k-NN 알고리즘에는 각 샘플의 특성 벡터 표현 및 계산할 측정항목 두 벡터 사이의 거리를 줄여 포즈 샘플에 가장 가까운 타겟을 찾습니다. 즉, 방금 획득한 포즈 랜드마크를 변환해야 합니다.
포즈 랜드마크를 특징 벡터로 변환하려면 쌍 거리 거리를 사용합니다. 사전 정의된 포즈 관절 목록(예: 손목과 손목과 어깨, 발목 및 엉덩이, 좌우 손목과 골반이 있습니다. 이미지의 크기가 몸통 크기와 수직 몸통이 같도록 포즈를 정규화했습니다. 방향을 전환할 수 있습니다.
3. 모델 학습 및 반복 횟수 계산
MediaPipe Colab을 사용하여 분류기의 코드에 액세스했습니다. 모델을 학습시킬 수 있습니다
반복 횟수를 계산하기 위해 다른 Colab 알고리즘을 사용하여 확률을 모니터링했습니다. 임곗값입니다. 예를 들면 다음과 같습니다.
- '다운' 확률이 포즈 클래스가 알고리즘은 '다운' 버튼을 포즈 클래스가 입력됩니다.
- 가능성이 임곗값 아래로 떨어지면 알고리즘은 '아래로' 포즈 클래스가 종료되고 카운터가 증가합니다.
![](https://developers.google.cn/static/ml-kit/images/vision/pose-detection/pose_classification.gif?authuser=0000&hl=ko)
4. ML Kit 빠른 시작 앱과 통합
위의 Colab은 모든 포즈로 채울 수 있는 CSV 파일을 생성합니다. 샘플입니다. 이 섹션에서는 CSV 파일을 ML Kit Android 빠른 시작 앱을 사용하여 실시간으로 맞춤 포즈 분류를 확인하세요.
빠른 시작 앱에 번들로 포함된 샘플로 포즈 분류 사용해 보기
- ML Kit Android 빠른 시작 앱 프로젝트 가져오기 빌드 및 실행을 확인합니다
LivePreviewActivity
페이지로 이동하여 자세 감지를 사용 설정하세요.Run classification
'설정'에서 있습니다. 이제 푸시업과 스쿼트를 분류할 수 있습니다.
자체 CSV 추가
- 앱의 애셋 폴더에 CSV 파일을 추가합니다.
- PoseClassifierProcessor는 다음과 같습니다.
POSE_SAMPLES_FILE
및POSE_CLASSES
변수를 CSV 파일과 포즈 샘플에 대해 알아보세요. - 앱을 빌드하고 실행합니다.
샘플이 충분하지 않으면 분류가 제대로 작동하지 않을 수 있습니다. 일반적으로 포즈 클래스당 약 100개의 샘플이 필요합니다.
자세히 알아보고 직접 사용해 보려면 MediaPipe Colab을 확인하세요. 및 MediaPipe 분류 가이드입니다.
명소 거리를 계산하여 간단한 동작 인식
두 개 이상의 랜드마크가 서로 가까이 있는 경우 동작을 인식할 수 있습니다. 예를 들어 손가락 한 개에 대한 랜드마크가 코의 이 부위에 손이 가까우면 사용자가 가장 잘 맞는지 추론할 수 있습니다. 얼굴에 갖다 대고 있을 가능성이 높기 때문입니다.
![](https://developers.google.cn/static/ml-kit/images/vision/pose-detection/touching_face.gif?authuser=0000&hl=ko)
각도 휴리스틱으로 요가 자세 알아보기
다양한 관절의 각도를 계산하여 요가 자세를 식별할 수 있습니다. 대상 아래 그림 2는 Warrior II 요가 자세를 보여줍니다. 대략적인 각도 다음과 같이 쓰여 있습니다.
![](https://developers.google.cn/static/ml-kit/images/vision/pose-detection/warrier2_sketch.png?authuser=0000&hl=ko)
이 자세는 다음과 같이 신체를 대략적으로 조합한 것으로 설명할 수 있습니다. 파트 각도:
- 양쪽 어깨에서 90도 각도
- 양쪽 팔꿈치 180도
- 90도 각도로 앞 다리와 허리
- 뒤쪽 무릎을 180도 각도로
- 허리 각도 135도
랜드마크를 사용하여 이러한 각도를 계산할 수 있습니다. 예를 들어 오른쪽 앞 다리와 허리의 각도는 오른쪽과 선 사이의 어깨에서 오른쪽 엉덩이까지, 오른쪽 엉덩이에서 오른쪽 무릎까지의 라인입니다.
포즈를 식별하는 데 필요한 모든 각도를 계산하고 나면 포즈를 인식한 경우입니다.
아래의 코드 스니펫은 X 및 Y 좌표를 사용하여 두 신체 부위 사이의 각도를 계산합니다. 이러한 분류 접근 방식 몇 가지 제한사항이 있습니다 X와 Y만 확인하면 계산된 각도가 달라집니다. 피사체와 카메라 사이의 각도에 따라 촬영됩니다. 여러분은 정면을 보여주는 평평하고 직선적인 이미지로 최상의 결과를 얻는 것이 중요합니다. 또한 다음을 수행할 수도 있습니다. 인코더-디코더 아키텍처를 활용하여 Z 좌표 성능이 사용 사례에 더 적합한지 확인해 보세요.
Android에서 명소 각도 계산
다음 메서드는 3과 1 사이의 각도를 계산합니다. 있습니다. 반환되는 각도가 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 }
자바
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))
자바
double rightHipAngle = getAngle( pose.getPoseLandmark(PoseLandmark.Type.RIGHT_SHOULDER), pose.getPoseLandmark(PoseLandmark.Type.RIGHT_HIP), pose.getPoseLandmark(PoseLandmark.Type.RIGHT_KNEE));
iOS에서 명소 각도 계산
다음 메서드는 3과 1 사이의 각도를 계산합니다. 있습니다. 반환되는 각도가 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]];