머신러닝 & 딥러닝

[openpose] 이미지에서 관절 포인트 검출하기

김먼저 2023. 5. 17. 10:56

smplify-x 를 실행시키기 위해서는 이미지과 해당 이미지의 관절포인트가 있는 keypoints.json 파일이 필요하여

 

openpose를 실행시켜 json 파일을 얻기 위해 실행하게 되었습니다.

 

그러나 이 방법으로는 keypoints.json 데이터를 얻을 수가 없어 방법을 찾게 된다면 포스팅하도록 하겠습니다.

 

다음 방법은 openpose.zip 파일을 다운받아 실행시키는 방법으로 진행하였습니다.

 

1. GitHub에서 openpose를 다운로드 받습니다.

 

https://github.com/CMU-Perceptual-Computing-Lab/openpose

 

GitHub - CMU-Perceptual-Computing-Lab/openpose: OpenPose: Real-time multi-person keypoint detection library for body, face, hand

OpenPose: Real-time multi-person keypoint detection library for body, face, hands, and foot estimation - GitHub - CMU-Perceptual-Computing-Lab/openpose: OpenPose: Real-time multi-person keypoint de...

github.com

 

 

다운로드가 완료되면, 압축을 푼 후에

 

openpose-master\models 에 있는 getModels.bat를 실행시켜줍니다.

 

 

실행시키면 아래와 같은 창이 뜨면서 모델들을 다운로드하기 시작합니다.

 

(시간이 조금 걸립니다. 15분있다가 오니까 다 설치되었네요.)

 

 

2. Model 셋팅

 

pose 폴더에는  body_25, coco, mpi 3가지 폴더가 있으며 각 폴더에는 해당 이름에 맞는 모델, 가중치 데이터가 있습니다.

 

사용할 모델을 선택한 뒤 경로만 설정 및 Body_Pairs, Pose_Pairs 를 형식에 맡게 변경해주시면 됩니다.

 

저는 mpi폴더에 있는 모델데이터로 테스트를 진행하였습니다.

 

MPII Human Pose Dataset에서 훈련된 관절 검출 모델입니다.

 

첫번째 파일 pose_deploy_linevec.prototxt는

 

아래에 있는 pose_deploy_linevec_faster_4_stages.prototxt 보다 무겁지만 정확한 모델입니다.

 

.prototxt : 모델의 구성요소에 대한 정보.
.caffemodel : 훈련된 모델 가중치를 저장.

 

3. 개발 환경 셋팅

파이선 코드를 실행시킬 수 있는 IDE를 이용해서 개발 환경을 셋팅합니다.

 

opencv가 꼭 필요하니 설치해줍니다.

 

pip install opencv-python

 

저는 파이참으로 새 프로젝트를 생성한 뒤 main.py에 다음 코드를 가져왔습니다.

 

# This is a sample Python script.

# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
import cv2

def print_hi(name):
    # Use a breakpoint in the code line below to debug your script.
    # MPII에서 각 파트 번호, 선으로 연결될 POSE_PAIRS
    BODY_PARTS = {"Head": 0, "Neck": 1, "RShoulder": 2, "RElbow": 3, "RWrist": 4,
                  "LShoulder": 5, "LElbow": 6, "LWrist": 7, "RHip": 8, "RKnee": 9,
                  "RAnkle": 10, "LHip": 11, "LKnee": 12, "LAnkle": 13, "Chest": 14,
                  "Background": 15}

    POSE_PAIRS = [["Head", "Neck"], ["Neck", "RShoulder"], ["RShoulder", "RElbow"],
                  ["RElbow", "RWrist"], ["Neck", "LShoulder"], ["LShoulder", "LElbow"],
                  ["LElbow", "LWrist"], ["Neck", "Chest"], ["Chest", "RHip"], ["RHip", "RKnee"],
                  ["RKnee", "RAnkle"], ["Chest", "LHip"], ["LHip", "LKnee"], ["LKnee", "LAnkle"]]

        #COCO
    #Output
    #Format
    #Nose – 0, Neck – 1, Right
    #Shoulder – 2, Right
    #Elbow – 3, Right
    #Wrist – 4, Left
    #Shoulder – 5, Left
    #Elbow – 6, Left
    #Wrist – 7, Right
    #Hip – 8, Right
    #Knee – 9, Right
    #Ankle – 10, Left
    #Hip – 11, Left
    #Knee – 12, LAnkle – 13, Right
    #Eye – 14, Left
    #Eye – 15, Right
    #Ear – 16, Left
    #Ear – 17, Background – 18

        #MPII
    #Output
    #Format
    #Head – 0, Neck – 1, Right
    #Shoulder – 2, Right
    #Elbow – 3, Right
    #Wrist – 4, Left
    #Shoulder – 5, Left
    #Elbow – 6, Left
    #Wrist – 7, Right
    #Hip – 8, Right
    #Knee – 9, Right
    #Ankle – 10, Left
    #Hip – 11, Left
    #Knee – 12, Left
    #Ankle – 13, Chest – 14, Background – 15

    # 각 파일 path
    protoFile = "C:\\openpose_data\\pose_deploy_linevec.prototxt"
    weightsFile = "C:\\openpose_data\\pose_iter_160000.caffemodel"

    # 위의 path에 있는 network 불러오기
    net = cv2.dnn.readNetFromCaffe(protoFile, weightsFile)

    # 이미지 읽어오기
    image = cv2.imread("C:\\openpose_data\\model.jpg")

    # frame.shape = 불러온 이미지에서 height, width, color 받아옴
    imageHeight, imageWidth, _ = image.shape

    # network에 넣기위해 전처리
    inpBlob = cv2.dnn.blobFromImage(image, 1.0 / 255, (imageWidth, imageHeight), (0, 0, 0), swapRB=False, crop=False)

    # network에 넣어주기
    net.setInput(inpBlob)

    # 결과 받아오기
    output = net.forward()

    # output.shape[0] = 이미지 ID, [1] = 출력 맵의 높이, [2] = 너비
    H = output.shape[2]
    W = output.shape[3]
    print("이미지 ID : ", len(output[0]), ", H : ", output.shape[2], ", W : ", output.shape[3])  # 이미지 ID

    # 키포인트 검출시 이미지에 그려줌
    points = []
    # for i int range(len()):
        # coco
    # for i in range(0,18)
    for i in range(0, 15):
        # 해당 신체부위 신뢰도 얻음.
        probMap = output[0, i, :, :]

        # global 최대값 찾기
        minVal, prob, minLoc, point = cv2.minMaxLoc(probMap)

        # 원래 이미지에 맞게 점 위치 변경
        x = (imageWidth * point[0]) / W
        y = (imageHeight * point[1]) / H

        # 키포인트 검출한 결과가 0.1보다 크면(검출한곳이 위 BODY_PARTS랑 맞는 부위면) points에 추가, 검출했는데 부위가 없으면 None으로
        # if prob > threshold :
        if prob > 0.1:
            cv2.circle(image, (int(x), int(y)), 3, (0, 255, 255), thickness=-1,
                       lineType=cv2.FILLED)  # circle(그릴곳, 원의 중심, 반지름, 색)
            cv2.putText(image, "{}".format(i), (int(x), int(y)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1,
                        lineType=cv2.LINE_AA)
            points.append((int(x), int(y)))
        else:
            points.append(None)

    cv2.imshow("Output-Keypoints", image)
    cv2.waitKey(0)

    # 이미지 복사
    imageCopy = image

    # 각 POSE_PAIRS별로 선 그어줌 (머리 - 목, 목 - 왼쪽어깨, ...)
    for pair in POSE_PAIRS:
        partA = pair[0]  # Head
        partA = BODY_PARTS[partA]  # 0
        partB = pair[1]  # Neck
        partB = BODY_PARTS[partB]  # 1

        # print(partA," 와 ", partB, " 연결\n")
        if points[partA] and points[partB]:
            cv2.line(imageCopy, points[partA], points[partB], (0, 255, 0), 2)

    cv2.imshow("Output-Keypoints", imageCopy)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    print_hi('PyCharm')

# See PyCharm help at https://www.jetbrains.com/help/pycharm/

 

위 코드에서 셋팅해야할 부분은 3가지 입니다.

 

protoFile = "C:\\openpose_data\\pose_deploy_linevec.prototxt"
weightsFile = "C:\\openpose_data\\pose_iter_160000.caffemodel"
image = cv2.imread("C:\\openpose_data\\model.jpg")

 

위에 모델, 모델 가중치, 테스트 할 이미지파일 경로를 셋팅하고 실행시키면

 

 

 

 

...얼추 맞긴하지만 약간 이상하네요....

 

coco는 테스트 하고 올리겠습니다!