1. Test에 필요한 정보 json에 저장

PyQT에서 사용하기 쉽도록 필요한 정보를 json에 담아 서버에 저장하는 작업을 하였다.

1-1) Bounding Box 개수 세기

해당 모델은 “단일 심층 신경망을 사용하여 이미지에서 물체를 감지하는 방법“을 설명하는 SSD: Single Shot MultiBox Detector 논문을 기반으로 작성되었다.

[ 출처 : 파이토치 공식 문서 ]


위 문서에도 설명되어 있듯이, 프로젝트에서 사용한 모델은 coco 데이터셋으로 사전학습 된 SSD 모델을 사용한다. transform된 이미지를 tensor로 변환 후 SSD 네트워크를 실행하여 객체를 탐지한다. SSD 네트워크의 기본 출력값은 객체의 위치를 식별하는 여러개의 bounding 박스와 클래스, confidence 값을 담고있다. box들 중에서 confidence가 0.45이상인 박스만 1차적으로 걸러내고, for문을 돌면서 threshold 값보다 작은 confidence의 box는 continue로 건너뛴다. 따라서 Bounding Box의 개수를 세기 위해서 count 변수를 생성하여 continue 문 밑에 count를 늘려주는 코드를 작성하였다. 자세한 코드는 보안문제로 생략한다.


...
results_per_input = utils.decode_results(detections_batch)
best_results_per_input = [utils.pick_best(results, 1 conf.) for results in results_per_input]

for image_idx in range(len(best_results_per_input)):
    cnt = 0 # new var

    ...

    for idx in range(len(bboxes)):
        ...
        if ... confidences[idx] < 0.6:
            continue
        
        cnt += 1

    ...

return ... cnt    


1-2) 투기여부 Boolean 값 형변환

의미를 명확하게 하기 위해서, boolean 타입의 dumping_yn의 값을 ‘Y’ 또는 ‘N’으로 바꾸어 주었다.

dumping_yn = True # or False
return 'Y' if dumping_yn==True else 'N' ...


1-3) json에 담아서 저장

dumping_yn은 dumping_yn에, cnt는 people에 저장한 뒤, json으로 만들어 res_filename.json 형태로 저장해주었다. 한 눈에 보기 쉽게 indent 옵션도 넣어주었다.

...

dumping_yn, cnt, ... = func(image)     

data = {
    'dumping_yn' : [dumping_yn],
    'people' : [cnt]
}                                 

with open( os.path.join(SAVE_DIR, dir) +'/res'+ file_name[4:] +'.json', 'w') as outfile:
    json.dump(data, outfile, indent=4)

...
{
    "dumping_yn": [
        "N"
    ],
    "people": [
        1
    ]
}



2. Bounding Box만 나오는 이미지 생성

모델 평가 항목이 객체 검출률과, 투기 행위 인식률인 관계로 Bounding Box만 그려진 이미지도 필요했다. 따라서 Bounding Box만 그려진 이미지도 함수 리턴값에 추가해주었다.

2-1) 처음 생각한 방법

rectangle을 그려주는 코드 바로 아래에, image를 deep copy하여 box_image에 저장해주고, 이를 return하는 방식을 생각하였다. 하지만 이런 로직을 사용하면, 객체가 여러개일 때 문제가 발생한다. 첫 for문이 돌 때는 box_image에 스켈레톤이 그려지지 않은 이미지가 정상적으로 출력되지만, 그 다음 for문부터는 이미지가 다시 원상복구 되는 문제가 발생했다. 또한, 검출된 객체가 없을때는 box_image가 선언되지 않아서 return단에서 예외처리를 해주어야 했다.


for image_idx in range(len(best_results_per_input)):
    cnt = 0 # new var

    ...

    cv2.rectangle(image, (x1, y1), (x2, y2), (0, 0, 255), 2, cv2.LINE_AA)
    box_image = image.copy()

    ...

return ... box_image ...


2-2) 이미지 분리

다음과 같이 애초에 box_image와 image를 분리하는 방식으로 해당 이슈를 해결하였다. 객체가 여러개여도 box_image에는 bounding box만 그려지게 되고, 객체가 검출되지 않는 경우에는 box_image는 원본 이미지와 같아지게 된다.


box_image = image.copy()
for image_idx in range(len(best_results_per_input)):
    cnt = 0 # new var

    ...

    cv2.rectangle(image, (x1, y1), (x2, y2), (0, 0, 255), 2, cv2.LINE_AA)
    cv2.rectangle(box_image, (x1, y1), (x2, y2), (0, 0, 255), 2, cv2.LINE_AA)

    ...

return ... box_image ...



3. output

3-1) Only Box Image

image

3-2) Output Image

image

3-3) Json File

{
    "dumping_yn": [
        "N"
    ],
    "people": [
        2
    ]
}

댓글남기기