본문 바로가기
python/딥러닝

[컴퓨터 비전] OpenCV 안에 있는 Detection 모델 사용하기

by _avocado_ 2021. 4. 29.
인프런 - 권철민 님의 '딥러닝 컴퓨터 비전 완벽 가이드'를 정리한 내용입니다.

OpenCV Detection 모델

openCV를 설치하면 딥러닝 프레임워크가 없더라도 사용 가능한 모델을 제공한다.

 

OpenCV에서 지원하는 Computer Vision 처리 기능과 딥러닝을 쉽게 결합하여 사용할 수 있다.

 

● 단점

 

- GPU 지원이 약하다.

 

- 학습은 불가능하며 오직 inference만 가능하다.

 

- 다른 딥러닝 프레임워크를 사용했을 때 보다 느리다.


딥러닝 모델 load 하기

자체적으로 가중치 모델을 생성하지 않고 다른 프레임워크에서 생성된 모델을 변환하여 로딩하는 방식이다.

 

가중치 모델 파일환경 파일을 필요로 한다. (각 사이트에서 받을 수 있다.)

import cv2

# Tensorflow

cvNet = cv2.dnn.readNetFromTensorflow('가중치 모델 파일','환경 파일')

# Darknet (Yolo만 가능)

cvNet = cv2.dnn.readNetFromDarknet('가중치 모델 파일','환경 파일')

# Torch

cvNet = cv2.dnn.readNetFromTorch('가중치 모델 파일','환경 파일')

# Caffe

cvNet = cv2.dnn.readNetFromCaffe('가중치 모델 파일','환경 파일')

● Tensorflow 모델 가중치 및 환경 파일 다운로드

 

아래 링크에서 그림과 같이 다운로드할 수 있다.

 

링크 :  github.com/opencv/opencv/wiki/TensorFlow-Object-Detection-API


OpenCV DNN을 이용한 Inference 수행 절차

1. 모델을 load 한다.

2. 이미지를 preprocessing하여 모델에 입력한다.

3. Output을 받는다.

4. 출력된 결과를 바탕으로 시각화등에 이용한다.

1. 모델을 load 한다.

import cv2

# 모델 load

cv_net = cv2.dnn.readNetFromTensorflow('가중치 모델 파일','환경 파일')

2. 이미지를 preprocessing하여 모델에 입력한다.

# 이미지 load

img = cv2.imread(os.path.join(default_dir,'data/image/beatles01.jpg'))

# 원본 이미지 shape, 시각화 할 때 필요하다.

rows,cols = img.shape[0], img.shape[1]

draw_img = img.copy() # 원본 이미지는 보존하면서 시각화하기 위해

# 이미지를 모델에 입력하기

# 원본 이미지 배열 BGR을 RGB로 변환하여 배열 입력. swapRB

# Tensorflow Faster RCNN은 size를 고정할 필요가 없는 것으로 추정. 

cv_net.setInput(cv2.dnn.blobFromImage(img, swapRB=True, crop=False))

3. Output을 받는다.

# output

cv_out = cv_net.forward()

# cv_out.shape = [1,1,Detection 된 이미지수, 7] # 이미지를 1개만 넣었기 때문에

# Detection된 이미지별 각 결과 가져오기

for detection in cv_out[0,0,:,:]:
	
    class_id = detection[1]
    
    score = detection[2]
    
    left = detection[3] * cols
    
    top = detection[4] * rows
    
    right = detection[5] * cols
    
    bottom = detection[6] * rows

output의 형태는 4차원이다. 이미지 1개만을 넣었기 때문에 [1, 1, Detection 된 이미지수, 7]의 shape를 가지게 된다.

 

Detection된 이미지에 대해 7개의 정보를 가지고 있다. 0번 Index는 아무 정보 없고

 

1번 : 분류 class, 2번 : score(0~1), 3~6번은 좌표정보(0~1)을 갖는다. 좌표 정보는 0~1 값으로 비율로 나와있기 때문에

 

입력 이미지의 가로, 세로 값을 곱해주어 이미지 상의 좌표를 얻는다.

 

4. 출력된 결과를 바탕으로 시각화등에 이용한다.

labels_to_names = 숫자 라벨과 문자 라벨의 딕셔너리(아래설명)

# 라벨 이름과 점수를 caption으로 이미지에 입력한다.

caption = "{}: {:.4f}".format(labels_to_names[class_id], score)

# Detection된 이미지에 직사각형 박스를 그려준다.

# cv2.rectangle()은 인자로 들어온 draw_img에 사각형을 그림. 위치 인자는 반드시 정수형.

green_color=(0, 255, 0) # 박스 초록색

red_color=(0, 0, 255) # caption 빨간색

cv2.rectangle(draw_img, (int(left), int(top)), (int(right), int(bottom)), color=green_color, thickness=2)

cv2.putText(draw_img, caption, (int(left), int(top - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.4, red_color, 1)

● 모델별 label dictionary

 

MS-coco 데이터를 기준으로 각 모델들의 label dictionary가 다르다.

  모델 종류 라벨 종류
OpenCV DNN Tensorflow Faster RCNN 모델 1번
Tensorflow SSD 모델 2번
Tensorflow Mask RCNN 모델 1번
Darknet YOLO 모델 3번
# 1번

labels_to_names = {0:'person',1:'bicycle',2:'car',3:'motorcycle',4:'airplane',5:'bus',6:'train',7:'truck',8:'boat',9:'traffic light',
                   10:'fire hydrant',11:'street sign',12:'stop sign',13:'parking meter',14:'bench',15:'bird',16:'cat',17:'dog',18:'horse',19:'sheep',
                   20:'cow',21:'elephant',22:'bear',23:'zebra',24:'giraffe',25:'hat',26:'backpack',27:'umbrella',28:'shoe',29:'eye glasses',
                   30:'handbag',31:'tie',32:'suitcase',33:'frisbee',34:'skis',35:'snowboard',36:'sports ball',37:'kite',38:'baseball bat',39:'baseball glove',
                   40:'skateboard',41:'surfboard',42:'tennis racket',43:'bottle',44:'plate',45:'wine glass',46:'cup',47:'fork',48:'knife',49:'spoon',
                   50:'bowl',51:'banana',52:'apple',53:'sandwich',54:'orange',55:'broccoli',56:'carrot',57:'hot dog',58:'pizza',59:'donut',
                   60:'cake',61:'chair',62:'couch',63:'potted plant',64:'bed',65:'mirror',66:'dining table',67:'window',68:'desk',69:'toilet',
                   70:'door',71:'tv',72:'laptop',73:'mouse',74:'remote',75:'keyboard',76:'cell phone',77:'microwave',78:'oven',79:'toaster',
                   80:'sink',81:'refrigerator',82:'blender',83:'book',84:'clock',85:'vase',86:'scissors',87:'teddy bear',88:'hair drier',89:'toothbrush',
                   90:'hair brush'}
# 2번

labels_to_names = {1:'person',2:'bicycle',3:'car',4:'motorcycle',5:'airplane',6:'bus',7:'train',8:'truck',9:'boat',10:'traffic light',
                   11:'fire hydrant',12:'street sign',13:'stop sign',14:'parking meter',15:'bench',16:'bird',17:'cat',18:'dog',19:'horse',20:'sheep',
                   21:'cow',22:'elephant',23:'bear',24:'zebra',25:'giraffe',26:'hat',27:'backpack',28:'umbrella',29:'shoe',30:'eye glasses',
                   31:'handbag',32:'tie',33:'suitcase',34:'frisbee',35:'skis',36:'snowboard',37:'sports ball',38:'kite',39:'baseball bat',40:'baseball glove',
                   41:'skateboard',42:'surfboard',43:'tennis racket',44:'bottle',45:'plate',46:'wine glass',47:'cup',48:'fork',49:'knife',50:'spoon',
                   51:'bowl',52:'banana',53:'apple',54:'sandwich',55:'orange',56:'broccoli',57:'carrot',58:'hot dog',59:'pizza',60:'donut',
                   61:'cake',62:'chair',63:'couch',64:'potted plant',65:'bed',66:'mirror',67:'dining table',68:'window',69:'desk',70:'toilet',
                   71:'door',72:'tv',73:'laptop',74:'mouse',75:'remote',76:'keyboard',77:'cell phone',78:'microwave',79:'oven',80:'toaster',
                   81:'sink',82:'refrigerator',83:'blender',84:'book',85:'clock',86:'vase',87:'scissors',88:'teddy bear',89:'hair drier',90:'toothbrush',
                   91:'hair brush'}
# 3번

labels_to_names_seq = {0:'person',1:'bicycle',2:'car',3:'motorbike',4:'aeroplane',5:'bus',6:'train',7:'truck',8:'boat',9:'traffic light',10:'fire hydrant',
                       11:'stop sign',12:'parking meter',13:'bench',14:'bird',15:'cat',16:'dog',17:'horse',18:'sheep',19:'cow',20:'elephant',
                       21:'bear',22:'zebra',23:'giraffe',24:'backpack',25:'umbrella',26:'handbag',27:'tie',28:'suitcase',29:'frisbee',30:'skis',
                       31:'snowboard',32:'sports ball',33:'kite',34:'baseball bat',35:'baseball glove',36:'skateboard',37:'surfboard',38:'tennis racket',39:'bottle',40:'wine glass',
                       41:'cup',42:'fork',43:'knife',44:'spoon',45:'bowl',46:'banana',47:'apple',48:'sandwich',49:'orange',50:'broccoli',
                       51:'carrot',52:'hot dog',53:'pizza',54:'donut',55:'cake',56:'chair',57:'sofa',58:'pottedplant',59:'bed',60:'diningtable',
                       61:'toilet',62:'tvmonitor',63:'laptop',64:'mouse',65:'remote',66:'keyboard',67:'cell phone',68:'microwave',69:'oven',70:'toaster',
                       71:'sink',72:'refrigerator',73:'book',74:'clock',75:'vase',76:'scissors',77:'teddy bear',78:'hair drier',79:'toothbrush'}

● 결과

댓글