인물분류 api 명세 수정 - 100-hours-a-week/5-yeosa-wiki GitHub Wiki

1. 개요

  • 인물 분류 모델은 기존에 아래와 같은 형식으로 응답을 보냈다.

    {
        "message": "success",
        "data": [
            [
                "img073.jpg",
                "img010.jpg",
                "img004.jpg",
                "img081.jpg",
                "img063.jpg",
                "img064.jpg",
                "img084.jpg",
                "img025.jpg",
                "img058.jpg"
            ],
            [
                "img084.jpg",
                "img025.jpg",
                "img058.jpg"
            ],
            [,
                "img064.jpg",
                "img084.jpg",
                "img025.jpg",
                "img058.jpg"
            ],
            [,
                "img096.jpg",
                "img065.jpg",
                "img028.jpg"
            ]
        ]
    }
    
  • 그러나 프론트에서 해당 클러스터의 인물을 UI에 띄워주기 위해서는 ai 서버에서 얼굴 부분의 좌표가 사진 내에서 어디인지 응답으로 보내줘야 한다.

  • 그래서 아래와 같이 api 명세가 달라지게 되었다.

    {
      "message": "success",
      "data": [
        {
          "images": ["img1.jpg", "img3.jpg"],
          "representative_face": {
            "image": "img1.jpg",
            "bbox": [x1, y1, x2, y2]  // 첫 번째 이미지 기준 얼굴 좌표
          }
        },
        {
          "images": ["img2.jpg", "img4.jpg"],
          "representative_face": {
            "image": "img2.jpg",
            "bbox": [x1, y1, x2, y2]
          }
        }
      ]
    }
    
  • 이에 따라 비지니스 로직 상 수정이 필요한 상황이다.


2. 기존 방식

detector = yolo_detector
arcface = arcface_model

np_images = [np.array(img) for img in images]
bboxes_list, landmarks_list = detector.predict(np_images)

crops = []
mapped_names = []

for idx, (img, bboxes, landmarks) in enumerate(
    zip(np_images, bboxes_list, landmarks_list)
):
    if len(landmarks) > 0:
        aligned = detector.align(img, landmarks)
        for face in aligned:
            crops.append(face)
            mapped_names.append(file_names[idx])
  • zip(np_images, bboxes_list, landmarks_list)
    • 이미지(img), 해당 이미지에서 검출된 얼굴의 바운딩 박스 목록(bboxes), 해당 이미지에서 검출된 얼굴 랜드마트 목록(landmarks)가 한 이미지 단위로 묶여서 idx와 함께 반복됨
  • crops(크롭된 얼굴)과 포함된 파일명(mapped_names)가 일대일 대응된다
np_images = [img0, img1, img2]
bboxes_list = [
    [bbox_0_0, bbox_0_1],       # img0의 얼굴 2개
    [bbox_1_0],                 # img1의 얼굴 1개
    [bbox_2_0, bbox_2_1, bbox_2_2]  # img2의 얼굴 3개
]
landmarks_list = [
    [lm_0_0, lm_0_1],           # img0의 얼굴 2개
    [lm_1_0],                   # img1의 얼굴 1개
    [lm_2_0, lm_2_1, lm_2_2]    # img2의 얼굴 3개
]
file_names = ["img0.jpg", "img1.jpg", "img2.jpg"]
  • 위와 같은 형식으로 각 데이터가 준비되어 있을 때, zip을 통해 동일 인덱스에 있는 요소끼리 묶음으로써 이미지 단위 처리가 가능하다.
# idx = 0
img      = img0
bboxes   = [bbox_0_0, bbox_0_1]
landmarks = [lm_0_0, lm_0_1]

# idx = 1
img      = img1
bboxes   = [bbox_1_0]
landmarks = [lm_1_0]

# idx = 2
img      = img2
bboxes   = [bbox_2_0, bbox_2_1, bbox_2_2]
landmarks = [lm_2_0, lm_2_1, lm_2_2]

3. 코드 수정 사항

a. 기존

  • 아래와 같이 얼굴과 파일명만 일대일대응.

    crops = []
    mapped_names = []
    

b. 변경 후

  • 얼굴별로 bbox도 함께 저장
    • 각 클러스터에서 첫 번째 얼굴의 bbox를 찾아서 함께 반환