[Yolov7] keypoints detection을 통해 허리부분 찾는 방법

Yeon·2023년 2월 2일
0

yolo

목록 보기
1/1
post-thumbnail

Yolov7을 통해서 Keypoints를 찾는 방법

with torch.no_grad() :
	 output = non_max_suppression_kpt(output, 
                                        0.25, # Confidence Threshold
                                        0.65, # IoU Threshold
                                        nc=model.yaml['nc'], # Number of Classes
                                        nkpt=model.yaml['nkpt'], # Number of Keypoints
                                        kpt_label=True)
     for k in range(len(output)) :
         output[k] = scale_coords(image.shape[2:], output[0], im0.shape).round()
         
     output = output_to_keypoint(output)
  • non_max_suppresion_kpt를 통해서 kpt를 찾아서 output에 저장한다.

  • 애초에 yolov7의 경우 image size가 640x640으로 들어가는 것이 일반적이다. Human bounding box를 원본 사진의 좌표를 얻고 싶었기에 scale_coords 함수를 이용해서 사이즈를 맞춰준다.

keypoints좌표

  • 사람의 keypoints가 잘 검출되었다면 output의 shape은 58개가 나올 것이다.

  • output의 구성은 위의 사진처럼 나올 것이다. 0번째와 1번째 index는 무시해도 될 것 같다.

  • 그 다음 오게되는 2,3,4,5 번째 index는 left-top x, left-top-y, right-bottom x, right-bottom y 순으로 나오게 된다. 그 옆에 오는 것은 conf를 의미하고 그 다음부터는 keypoint x,y, conf 순으로 계속 오게된다.

lf_sh_x = int((output[idx,25]) / ratio[1]) #left shoulder x
lf_sh_y = int((output[idx,26]) / ratio[0]) #left shoulder y
rh_sh_x = int((output[idx,22]) / ratio[1]) #right shoulder x
rh_sh_y = int((output[idx,23]) / ratio[0]) #right shoulder y
lf_waist_x = int((output[idx, 43]) / ratio[1]) #left waist x
lf_waist_y = int((output[idx, 44]) / ratio[0] ) #left waist x
rh_waist_x = int((output[idx, 40]) / ratio[1]) #right waist x
rh_waist_y = int((output[idx, 41]) / ratio[0] ) #right waist y
  • 22,23번째 index는 오른쪽 어깨의 x,y 좌표이고, 25,26번째 index는 왼쪽 어깨의 좌표를 의미한다.

  • 40,41번째 index는 오른쪽 치골의 x,y 좌표이고, 43,44번째 index는 왼쪽 치골의 좌표를 의미한다.

  • 그리고 resize 된 사진과 원래 사진의 크기를 나눠주면서 ratio를 구한다. 그리고 나온 좌표에 ratio를 나눠준다.

  • ratio[0]은 height ratio[1]은 width를 의미한다.

  • keypoints가 허리를 잡아준 것이 아니라 치골의 좌표를 나타내준다. 그래서 여러가지의 경우의 수를 생각해서 적절한 허리의 위치 값을 찾아줘야 한다. 여기서 말하는 경우의 수란 누워있는 경우엔 x좌표를 조절해줘야 한다. 반면에 서있는 경우에는 y좌표를 수정해줘야 한다.

설계그림

lf_diff_x = abs(lf_shoulder_x - lf_waist_x) #absolute value of left shoulder to left waist x
lf_diff_y = abs(lf_shoulder_y - lf_waist_y) #absolute value of left shoulder to left waist y
rh_diff_x = abs(rh_shoulder_x - rh_waist_x) #absolute value of right shoulder to right waist x
rh_diff_y = abs(rh_shoulder_y - rh_waist_y) #absolute value of right shoulder to right waist x

if lf_diff_x > lf_diff_y and rh_diff_x > rh_diff_y : #누워있을 경우, 
	max_X = max(lf_diff_x, rh_diff_x)                                         #
    if lf_waist_x > lf_shoulder_x : #이건 하나만 비교해도 될 것 같다. 왼쪽으로 누워있을때 머리-몸통-다리
	    lf_waist_x -= int((max_X * 0.21)) # 왼쪽으로 누워있을 경우
    	rh_waist_x -= int((max_X * 0.21)) # 왼쪽으로 누워있을 경우
    else :
        lf_waist_x += int((max_X * 0.21)) # 오른쪽으로 누워있을 경우
        rh_waist_x += int((max_X * 0.21)) # 오른쪽으로 누워있을 경우
else : #서있는 경우
	max_Y = max(lf_diff_y, rh_diff_y)
    lf_waist_y -= int((max_Y * 0.21))
    rh_waist_y -= int((max_Y * 0.21))
    
  • left shoulder, left waist의 x,y좌표의 절댓값 차와 right shoulder, right waist의 x,y좌표의 절댓값 차를 변수로 저장한다.

  • x좌표의 차와 y좌표의 차를 비교해서 x좌표가 큰지 y좌표가 큰지 찾아낸다.

    • 이것을 하는 이유는 누워있는지, 서있는지를 판단하기 위해서다. 누워있는 경우엔 x좌표의 차이가 크고 y좌표의 차가 미비할 것이다. 반면에 서있는 경우엔 x좌표의 차이는 미비하고, y좌표의 차가 더 클 것이다.
  • x좌표끼리에서 둘 중 더 큰 차이의 값을 max_X라는 변수에 담는다.

    • 이것또한 더 아래쪽에 있는 부분을 기준으로 잡기 위해서 이렇게 잡는다.
  • 나는 허리까지의 값을 max_X에다가 0.21을 곱한 위치만큼, 대략적으로 어꺠와 치골 사이의 79:21 위치에 허리가 위치한다고 생각했다.

  • 누워있는 경우에는 두 가지를 생각해줘야한다. 왼쪽으로 누워있는 경우와 오른쪽으로 누워있는 경우 모두를 생각해야한다. 왼쪽으로 누워있을 경우엔 수를 뺴줘야 한다. 반면에 오른쪽으로 누워있는 경우에는 수를 더해줘야 한다.

    • ➡️ 이것은 그림을 그려보면 쉽게 이해할 수 있을 것이다. 위 그림에도 그려봤는데, 내가 말하는 오른쪽으로 누운 것과 왼쪽으로 누운 것은 위의 그림을 참고하면 쉬울 것이다.
  • 그 외의 경우 y좌표가 x좌표보다 크다는 얘기는 서있거나 물구나무서기 자세로 있다는 얘기이다. 그런데 일반적인 사진에는 물구나무서기로 있는 사진은 없다고 가정하면 이것은 y좌표를 그냥 빼주면 된다.

keypoints 사진

⬆️ Keypoints of human


허리선과 어깨선

⬆️ 어깨선과 허리선을 그린 것


📘 참고문헌

Yolov7

profile
Viel Erfolg!

0개의 댓글