DataScience
article thumbnail
728x90

손의 모양과 움직임을 인식하는 능력은 다양한 기술 영역과 플랫폼에서 사용자 경험을 개선하는 데 중요한 구성 요소가 될 수 있습니다. 예를 들어, 수화 이해 및 손 제스처 제어를 위한 기반을 형성할 수 있으며 증강 현실에서 물리적 세계 위에 디지털 콘텐츠 및 정보를 오버레이할 수도 있습니다. 강력한 실시간 손 인식은 사람들에게 자연스럽게 다가오지만 손은 종종 스스로 또는 서로를 가리고(예: 손가락/손바닥 폐색 및 손 흔들기) 고대비 패턴이 부족하기 때문에 결정적으로 어려운 컴퓨터 비전 작업입니다.

MediaPipe Hands는 정확도가 높은 손 및 손가락 추적 솔루션입니다. 기계 학습(ML)을 사용하여 단일 프레임에서 손의 21개 3D 랜드마크를 추출합니다.

주로 강력한 데스크톱 환경에 의존하는 반면, MediaPipe는 휴대폰에서 실시간 성능을 달성하고 여러 손으로 확장할 수도 있습니다. 

그림 1. 추적된 3D 손 랜드마크는 다양한 음영의 점으로 표시되며 밝은 점은 카메라에 더 가까운 랜드마크를 나타냅니다.

ML 파이프라인

MediaPipe Hands는 함께 작동하는 여러 모델로 구성된 ML 파이프라인을 활용합니다. 전체 이미지에서 작동하고 방향이 지정된 손 경계 상자를 반환하는 손바닥 감지 모델입니다. 손바닥 감지기에 의해 정의된 잘린 이미지 영역에서 작동하고 충실도가 높은 3D 손 키포인트를 반환하는 손 랜드마크 모델입니다. 이 전략은 얼굴 탐지기를 얼굴 랜드마크 모델과 함께 사용하는 MediaPipe Face Mesh 솔루션에서 사용하는 것과 유사합니다.

정확하게 잘린 손 이미지를 손 랜드마크 모델에 제공하면 데이터 증대(예: 회전, 변환 및 크기 조정)의 필요성이 크게 줄어들고 대신 네트워크가 대부분의 용량을 좌표 예측 정확도에 전념할 수 있습니다. 또한 우리의 파이프라인에서는 이전 프레임에서 식별된 손 랜드마크를 기반으로 작물을 생성할 수 있으며 랜드마크 모델이 더 이상 손의 존재를 식별할 수 없는 경우에만 손바닥 감지가 호출되어 손을 다시 현지화합니다.

파이프라인은 손 표식 모듈  손 표식 추적 하위 그래프  사용하고 전용 손 렌더러 하위 그래프 를 사용하여 렌더링 하는 MediaPipe 그래프 로 구현됩니다 . 손 랜드마크 추적 하위 그래프 는 내부적 으로 동일한 모듈의 손 랜드마크 하위 그래프와 손바닥 감지 모듈 의 손바닥 감지 하위 그래프 를 사용합니다 .

 

모델

손바닥 감지 모델

초기 손 위치를 감지하기 위해 MediaPipe Face Mesh 의 얼굴 감지 모델과 유사한 방식으로 모바일 실시간 사용에 최적화된 단일 샷 감지기 모델을 설계했습니다 . 손을 감지하는 것은 확실히 복잡한 작업입니다. 라이트 모델  전체 모델 은 이미지 프레임에 상대적인 대규모 범위(~20x)로 일정하지 않은 다양한 손 크기에 작동해야 하며 가려진 손과 self로 가려진 손을 감지할 수 있어야 합니다. 얼굴은 예를 들어 눈과 입 영역에서 고대비 패턴을 갖는 반면, 손에는 이러한 특징이 없기 때문에 시각적 특징만으로는 안정적으로 감지하기가 비교적 어렵습니다. 대신 팔, 신체 또는 사람 특징과 같은 추가 컨텍스트를 제공하면 정확한 손 위치 파악에 도움이 됩니다.

먼저 손바닥과 주먹과 같은 단단한 물체의 경계 상자를 추정하는 것이 관절이 있는 손가락으로 손을 감지하는 것보다 훨씬 간단하기 때문에 손 감지기 대신 손바닥 감지기를 훈련시킵니다. 또한 손바닥은 더 작은 물체이기 때문에 비최대 억제 알고리즘은 악수와 같은 두 손이 self로 가려진 경우에도 잘 작동합니다. 또한 손바닥은 다른 종횡비를 무시하고 사각형 경계 상자(ML 용어로 앵커)를 사용하여 모델링할 수 있으므로 앵커 수를 3-5배로 줄일 수 있습니다. 둘째, 인코더-디코더 특징 추출기는 작은 물체에 대해서도 더 큰 장면 컨텍스트 인식을 위해 사용됩니다(RetinaNet 접근 방식과 유사). 마지막으로

위의 기술을 사용하여 손바닥 감지에서 평균 95.7%의 정확도를 달성했습니다. 일반 교차 엔트로피 손실을 사용하고 디코더를 사용하지 않으면 기준선이 86.22%에 불과합니다.

핸드 랜드마크 모델

전체 이미지에서 손바닥을 감지한 후 후속 손 랜드마크 모델 은 회귀를 통해 감지된 손 영역 내부의 21개의 3D 손-너클 좌표의 정확한 키포인트 현지화, 즉 직접 좌표 예측을 수행합니다. 이 모델은 일관된 내부 손 포즈 표현을 학습하고 부분적으로 보이는 손과 self-occlusions에도 강력합니다.

지상 실측 데이터를 얻기 위해 아래와 같이 21개의 3D 좌표로 ~30K 실제 이미지에 수동으로 주석을 달았습니다(해당 좌표별로 존재하는 경우 이미지 깊이 맵에서 Z 값을 가져옵니다). 가능한 손 포즈를 더 잘 다루고 손 형상의 특성에 대한 추가 감독을 제공하기 위해 다양한 배경 위에 고품질 합성 손 모델을 렌더링하고 해당 3D 좌표에 매핑합니다.

Fig 2. 21 hand landmarks.
Fig 3. Top: Aligned hand crops passed to the tracking network with ground truth annotation.
Bottom: Rendered synthetic hand images with ground truth annotation.

솔루션 API

Configuration Options

이름 지정 스타일과 가용성은 플랫폼/언어에 따라 약간 다를 수 있습니다.

STATIC_IMAGE_MODE

false로 설정 하면 솔루션이 입력 이미지를 비디오 스트림으로 처리합니다. 첫 번째 입력 이미지에서 손을 감지하려고 시도하고 감지에 성공하면 손 랜드마크를 추가로 현지화합니다. 후속 이미지에서 모든 max_num_hands 손이 감지되고 해당 손 랜드마크가 현지화되면 손을 추적하지 못할 때까지 다른 감지를 호출하지 않고 단순히 해당 랜드마크를 추적합니다. 이는 대기 시간을 줄이고 비디오 프레임 처리에 이상적입니다. true 로 설정하면 손 감지가 모든 입력 이미지에서 실행되며 관련이 없을 수 있는 정적 이미지 배치를 처리하는 데 이상적입니다. 기본값은 false입니다.

MAX_NUM_HANDS

감지할 최대 손 수입니다. 기본값은 2입니다.

MODEL_COMPLEXITY

손 랜드마크 모델의 복잡성: 0또는 1. 랜드마크 정확도와 추론 대기 시간은 일반적으로 모델 복잡성에 따라 증가합니다. 기본값은 1입니다.

MIN_DETECTION_CONFIDENCE

성공적인 것으로 간주되는 감지에 대한 손 감지 모델의 최소 신뢰 값([0.0, 1.0]). 기본값은 0.5입니다.

MIN_TRACKING_CONFIDENCE:

성공적으로 추적된 것으로 간주되는 손 랜드마크에 대한 랜드마크 추적 모델의 최소 신뢰 값( [0.0, 1.0]) 또는 그렇지 않으면 다음 입력 이미지에서 손 감지가 자동으로 호출됩니다. 더 높은 값으로 설정하면 대기 시간이 길어지는 대신 솔루션의 견고성을 높일 수 있습니다. static_image_mode  true이면 무시됩니다 . 여기서 손 감지는 단순히 모든 이미지에서 실행됩니다. 기본값은 0.5입니다.

 

Output

이름 지정 스타일은 플랫폼/언어에 따라 약간 다를 수 있습니다.

MULTI_HAND_LANDMARKS

감지/추적된 손 모음. 여기서 각 손은 21개의 손 랜드마크 목록으로 표시되고 각 랜드마크는 x, y및 z로 구성 됩니다. x, y각각 이미지 너비와 높이 [0.0, 1.0] 정규화됩니다 . z는 손목의 깊이를 원점으로 하는 랜드마크 깊이를 나타내며 값이 작을수록 랜드마크가 카메라에 가까워집니다. z의 규모 는 x와 거의 같은 척도를 사용합니다 .

MULTI_HAND_WORLD_LANDMARKS

각 손이 세계 좌표에서 21개의 손 랜드마크 목록으로 표시되는 감지/추적 손 모음입니다. 각 랜드마크는 x, y및  z로 구성됩니다. 실제 3D 좌표는 미터 단위이며 원점은 손의 대략적인 기하학적 중심입니다.

MULTI_HANDEDNESS

감지/추적된 손의 손의 수집(즉, 왼손인지 오른손인지). 각 핸드는 label및 score로 구성 됩니다. label는 "Left"또는 "Right"의 값 문자열입니다. score는 예측된 손의 예상 확률이며 0.5보다 항상 크거나 같습니다. (그리고 반대쪽 손의 예상 확률은 1 - score 입니다)

입력 이미지가 미러링된 것으로 가정(즉, 이미지가 수평으로 뒤집힌 전면/셀카 카메라로 촬영된 것으로 가정) 손을 사용하는지 여부가 결정됩니다. 그렇지 않은 경우 애플리케이션에서 handedness 출력을 교체하십시오.

 

코딩

1단계 - 가져오기 및 초기화

논의한 두 라이브러리를 가져오는 것으로 시작합니다. 라이브러리를 가져오면 종속성을 사용할 수 있습니다.

cap그런 다음 비디오 캡처를 위한 개체를 만듭니다 . 다음 MediaPipe 을 사용하여 입력을 조작하려면 다른 세 개체가 필요합니다 .

import cv2
import mediapipe as mp

cap = cv2.VideoCapture(0)
mpHands = mp.solutions.hands
hands = mpHands.Hands()
mpDraw = mp.solutions.drawing_utils

2단계 - 이미지 입력 ​​캡처 및 처리

아래 코드는 웹캠에서 이미지 입력을 받습니다. 그런 다음 이미지를 에서 로 변환 BGR합니다 RGB. RGB가 아닌 BGR이미지 MediaPipe에서만 작동 하기 때문 입니다.

그런 다음 이미지를 처리하여 RGB이미지에서 손을 식별합니다.

while True:
    success, image = cap.read()
    imageRGB = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    results = hands.process(imageRGB)

3단계 - 각 손으로 작업하기

    # checking whether a hand is detected
    if results.multi_hand_landmarks:
        for handLms in results.multi_hand_landmarks: # working with each hand
            for id, lm in enumerate(handLms.landmark):
                h, w, c = image.shape
                cx, cy = int(lm.x * w), int(lm.y * h)

위의 코드 if에서 손이 감지되었는지 확인하는 문을 사용합니다. 그런 다음 첫 번째 for루프를 사용하여 한 번에 한 손으로 작업할 수 있습니다.

두 번째 루프 는 손 랜드마크 다이어그램에 나열된 각 지점 의 및 좌표를 for제공하는 손 랜드마크 정보를 얻는 데 도움이 됩니다 . 이 루프는 또한 각 포인트의 id를 제공합니다.

그런 다음 image.shape함수 를 사용하여 이미지의 height, width및 channel를 찾습니다 . 마침내 식별된 손 포인트의 중앙 위치를 얻습니다.

4단계 - 손 이미지에 손 랜드마크 및 손 연결 그리기

                if id == 20 :
                    cv2.circle(image, (cx, cy), 25, (255, 0, 255), cv2.FILLED)

            mpDraw.draw_landmarks(image, handLms, mpHands.HAND_CONNECTIONS)

위의 코드에서 손 포인트 번호에 동그라미를 칩니다 20. 이것은 새끼 손가락의 끝입니다.

손 랜드마크 다이어그램에 나열되어 있으므로 원을 그리려는 손 포인트의 번호를 자유롭게 사용하십시오. 그런 다음 입력 이미지에 손 랜드마크와 이들 사이의 연결을 그립니다.

5단계 - 출력 표시

    cv2.imshow("Output", image)
    cv2.waitKey(1)

위의 코드를 사용하여 출력을 사용자에게 표시합니다. 출력은 사용자의 실시간 비디오입니다. 사용자의 손을 추적하고, 손의 랜드마크 및 손에 그려진 연결을 가지고 있습니다.

이 코드의 출력은 결과 섹션에 표시됩니다.

코드에서 모듈 만들기

새 파일을 만들고 이름을 handTrackingModule. 원하는 이름으로 자유롭게 이름을 지정하십시오. 이제 아래 단계에 따라 위의 코드에서 모듈을 만들어 보겠습니다.

1단계 - 필요한 라이브러리 가져오기

Python먼저 프로젝트에 필요한 라이브러리를 가져옵니다 . 이렇게 하면 종속성을 사용할 수 있습니다.

import cv2
import mediapipe as mp

2단계 - 손 감지에 사용할 클래스 만들기

class handTracker():
    def __init__(self, mode=False, maxHands=2, detectionCon=0.5,modelComplexity=1,trackCon=0.5):
        self.mode = mode
        self.maxHands = maxHands
        self.detectionCon = detectionCon
        self.modelComplex = modelComplexity
        self.trackCon = trackCon
        self.mpHands = mp.solutions.hands
        self.hands = self.mpHands.Hands(self.mode, self.maxHands,self.modelComplex,
                                        self.detectionCon, self.trackCon)
        self.mpDraw = mp.solutions.drawing_utils

위의 코드에서 추적에 사용할 클래스를 만듭니다. hands그런 다음 기능이 작동 하는 데 필요한 기본 매개변수를 입력 합니다. MediaPipe는 hands 함수에서 이러한 매개변수를 제공합니다.

그런 다음 클래스에 필요한 모든 초기화를 제공합니다. 위의 매개변수와 MediaPipe초기화입니다.

우리는 self해당 객체의 메서드 및 속성에 대한 액세스를 허용하기 위해 모든 객체 앞에 배치합니다. 이렇게 하면 각 개체가 고유한 특성과 메서드를 소유할 수 있습니다.

3단계 - 입력 이미지에서 손을 추적하는 방법 만들기

    def handsFinder(self,image,draw=True):
        imageRGB = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
        self.results = self.hands.process(imageRGB)

        if self.results.multi_hand_landmarks:
            for handLms in self.results.multi_hand_landmarks:

                if draw:
                    self.mpDraw.draw_landmarks(image, handLms, self.mpHands.HAND_CONNECTIONS)
        return image

위의 코드에서 입력 이미지의 손을 구체적으로 추적하는 데 사용할 메서드를 만들었습니다. 이 메서드에 들어가는 코드는 이미지를 변환하고 이미지를 RGB처리 RGB하여 손을 찾는 코드입니다.

또한 이미지에 손 랜드마크를 그리고 마지막으로 손 연결을 그립니다.

4단계 - 각 손 포인트의 'x' 및 'y' 좌표를 찾는 방법 만들기

    def positionFinder(self,image, handNo=0, draw=True):
        lmlist = []
        if self.results.multi_hand_landmarks:
            Hand = self.results.multi_hand_landmarks[handNo]
            for id, lm in enumerate(Hand.landmark):
                h,w,c = image.shape
                cx,cy = int(lm.x*w), int(lm.y*h)
                lmlist.append([id,cx,cy])
            if draw:
                cv2.circle(image,(cx,cy), 15 , (255,0,255), cv2.FILLED)

        return lmlist

위의 코드에서 우리는 21개의 손 포인트 각각의 x및 y좌표를 찾는 데 사용할 메서드를 만들었습니다. 또한 이러한 좌표 값을 저장하는 데 사용할 목록을 만들었습니다.

이 메서드에 들어가는 코드는 각 손 포인트의 id 및 손 랜드마크 정보를 찾는 데 사용하는 코드입니다. 또한 사용하려는 손 포인트를 원으로 표시하는 데 사용할 코드를 입력합니다.

5단계 - 기본 메서드 만들기

def main():
    cap = cv2.VideoCapture(0)
    tracker = handTracker()

    while True:
        success,image = cap.read()
        image = tracker.handsFinder(image)
        lmList = tracker.positionFinder(image)
        if len(lmList) != 0:
            print(lmList[4])

        cv2.imshow("Video",image)
        cv2.waitKey(1)

위의 코드는 모듈이 무엇을 할 수 있는지 보여주는 데 사용할 더미 코드를 나타냅니다. 우리의 경우 손을 식별하고 추적할 수 있습니다. image그리고 lmlist객체 를 사용 합니다. 이 코드는 기본 메서드에 나타납니다.

 

결과

프로그램과 모듈의 출력은 동일합니다. 각각 오류 없이 완료되면 출력은 다음과 같습니다.

'영상처리 > Recognition' 카테고리의 다른 글

SlowFast  (133) 2023.05.09
profile

DataScience

@Ninestar

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!