๋ฐ์ํ
OpenCV DNN ํจํค์ง๋ฅผ ์ด์ฉํ์ฌ SSD๊ธฐ๋ฐ Object Detection ์ํ
Tensorflow ์์ Pretrained ๋ ๋ชจ๋ธ ํ์ผ์ OpenCV์์ ๋ก๋ํ์ฌ ์ด๋ฏธ์ง์ ์์์ ๋ํ Object Detection์ ์ํํด๋ณด๊ฒ ์ต๋๋ค.
์ ๋ ฅ ์ด๋ฏธ์ง๋ก ์ฌ์ฉ๋ ์ด๋ฏธ์ง ๋ณด๊ธฐ
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
img = cv2.imread('../../data/image/beatles01.jpg')
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
print('image shape:', img.shape)
plt.figure(figsize=(12, 12))
plt.imshow(img_rgb)
- Tensorflow์์ Pretrained ๋ Inference๋ชจ๋ธ(Frozen graph)์ ํ๊ฒฝํ์ผ์ ๋ค์ด๋ก๋ ๋ฐ์ ํ ์ด๋ฅผ ์ด์ฉํด OpenCV์์ Inference ๋ชจ๋ธ์ ์์ฑํฉ๋๋ค.
- ์๋์ ๋ค์ด๋ก๋ URL์ด ์์ต๋๋ค.
- pretrained ๋ชจ๋ธ์ ์๋์ ๋งํฌ ์์ ๋ค์ด๋ก๋ ํ ์์ถ ํด์ ํ์๋ฉด ๋ฉ๋๋ค.
- pretrained ๋ชจ๋ธ์ ์ํ ํ๊ฒฝ ํ์ผ์ ์๋์ ๋งํฌ์์ ๋ค์ด๋ก๋ ํ์๋ฉด ๋ฉ๋๋ค.
- download๋ ๋ชจ๋ธ ํ์ผ๊ณผ config ํ์ผ์ ์ธ์๋ก ํ์ฌ inference ๋ชจ๋ธ์ DNN์์ ๋ก๋ฉํฉ๋๋ค.
# mkdir pretrained; cd pretrained
# wget http://download.tensorflow.org/models/object_detection/ssd_inception_v2_coco_2017_11_17.tar.gz
# wget https://raw.githubusercontent.com/opencv/opencv_extra/master/testdata/dnn/ssd_inception_v2_coco_2017_11_17.pbtxt
# cd ssd_inception_v2_coco_2017_11_17; mv ssd_inception_v2_coco_2017_11_17.pbtxt graph.pbtxt
# https://github.com/opencv/opencv_extra/blob/master/testdata/dnn/ssd_inception_v2_coco_2017_11_17.pbtxt?raw=true -O ./graph.pbtxt
!pwd
!ls pretrained/ssd_inception_v2_coco_2017_11_17
cv_net = cv2.dnn.readNetFromTensorflow('./pretrained/ssd_inception_v2_coco_2017_11_17/frozen_inference_graph.pb',
'./pretrained/ssd_inception_v2_coco_2017_11_17/graph.pbtxt')
OpenCV & Tensorflow์ CoCo ํด๋์ค ID & Name ๋งคํ
- Class id๊ฐ 0~90 ์ด๋ฉด TF์์ Faster R-CNN, Mask R-CNN ๋ชจ๋ธ ๋ก๋ํ ๋ ์ฌ์ฉ๋๋ Dataset ์ ๋๋ค.
- Class id๊ฐ 1~91 ์ด๋ฉด TF์์ SSD ๋ชจ๋ธ ๋ก๋ํ ๋ ์ฌ์ฉ๋๋ Dataset์ ๋๋ค.
- Class id๊ฐ 0~79 ์ด๋ฉด TF์์ DNN Darkent YOLO ๋ชจ๋ธ์ ๋ก๋ํ๋๋ฐ ์ฌ์ฉ๋๋ Dataset์ ๋๋ค.
labels_to_names_seq= {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'}
- ์ด๋ฌํ ํ์์ผ๋ก ๋ชจ๋ธ์์ Dataset์ ํด๋์ค ID๋ณ ํด๋์ค๋ช ์ ์ง์ ํฉ๋๋ค.
Image Preprocessing & Object Detection ์ํํ ๊ฒฐ๊ณผ ์๊ฐํ
์ด๋ฏธ์ง๋ฅผ preprocessing ์ํํ์ฌ Network์ ์ ๋ ฅํ๊ณ Object Detection ์ํ ํ ๊ฒฐ๊ณผ๋ฅผ ์ด๋ฏธ์ง์ ์๊ฐํ ํด๋ณด๊ฒ ์ต๋๋ค.
# ์๋ณธ ์ด๋ฏธ์ง (633, 806)๋ฅผ ๋คํธ์์ ์
๋ ฅ์์๋ (300, 300)๋ก resize ํจ.
# ์ดํ ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ๋๋ฉด resize๋ ์ด๋ฏธ์ง ๊ธฐ๋ฐ์ผ๋ก bounding box ์์น๊ฐ ์์ธก ๋๋ฏ๋ก ์ด๋ฅผ ๋ค์ ์๋ณตํ๊ธฐ ์ํด ์๋ณธ ์ด๋ฏธ์ง shape์ ๋ณด ํ์
rows = img.shape[0]
cols = img.shape[1]
# cv2์ rectangle()์ ์ธ์๋ก ๋ค์ด์จ ์ด๋ฏธ์ง ๋ฐฐ์ด์ ์ง์ ์ฌ๊ฐํ์ ์
๋ฐ์ดํธ ํ๋ฏ๋ก ๊ทธ๋ฆผ ํํ์ ์ํ ๋ณ๋์ ์ด๋ฏธ์ง ๋ฐฐ์ด ์์ฑ.
draw_img = img.copy()
# ์๋ณธ ์ด๋ฏธ์ง ๋ฐฐ์ด์ ์ฌ์ด์ฆ (300, 300)์ผ๋ก, BGR์ RGB๋ก ๋ณํํ์ฌ ๋ฐฐ์ด ์
๋ ฅ
cv_net.setInput(cv2.dnn.blobFromImage(img, size=(300, 300), swapRB=True, crop=False))
# Object Detection ์ํํ์ฌ ๊ฒฐ๊ณผ๋ฅผ cv_out์ผ๋ก ๋ฐํ
cv_out = cv_net.forward()
print(cv_out.shape)
# bounding box์ ํ
๋๋ฆฌ์ caption ๊ธ์์ ์ง์
green_color=(0, 255, 0)
red_color=(0, 0, 255)
# detected ๋ object๋ค์ iteration ํ๋ฉด์ ์ ๋ณด ์ถ์ถ
for detection in cv_out[0,0,:,:]:
score = float(detection[2])
class_id = int(detection[1])
# detected๋ object๋ค์ score๊ฐ 0.4 ์ด์๋ง ์ถ์ถ
if score > 0.4:
# detected๋ object๋ค์ image ํฌ๊ธฐ๊ฐ (300, 300)์ผ๋ก scale๋ ๊ธฐ์ค์ผ๋ก ์์ธก๋์์ผ๋ฏ๋ก ๋ค์ ์๋ณธ ์ด๋ฏธ์ง ๋น์จ๋ก ๊ณ์ฐ
left = detection[3] * cols
top = detection[4] * rows
right = detection[5] * cols
bottom = detection[6] * rows
# labels_to_names ๋์
๋๋ฆฌ๋ก class_id๊ฐ์ ํด๋์ค๋ช
์ผ๋ก ๋ณ๊ฒฝ. opencv์์๋ class_id + 1๋ก ๋งคํํด์ผํจ.
caption = "{}: {:.4f}".format(labels_to_names[class_id], score)
#cv2.rectangle()์ ์ธ์๋ก ๋ค์ด์จ draw_img์ ์ฌ๊ฐํ์ ๊ทธ๋ฆผ. ์์น ์ธ์๋ ๋ฐ๋์ ์ ์ํ.
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.7, red_color, 2)
print(caption, class_id)
img_rgb = cv2.cvtColor(draw_img, cv2.COLOR_BGR2RGB)
plt.figure(figsize=(12, 12))
plt.imshow(img_rgb)
- ํ๋ฒ ์ฝ๋ ์ค๋ช ์ ํด๋ณด๊ฒ ์ต๋๋ค.
- cv_out ๋ฐฐ์ด์ ์ ์ฅ๋ ๊ฐ์ฒด ๊ฒ์ถ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ๋ณตํ์ฌ ๊ฐ ๊ฐ์ฒด์ ๋ํด ์ ๋ณด๋ฅผ ์ถ์ถํฉ๋๋ค.
- ๊ฐ์ฒด ๊ฒ์ถ ์ ๋ขฐ๋ ์ ์์ธ score๊ฐ 0.4 ์ด์์ธ ๊ฒฝ์ฐ์๋ง ๋ค์ ๋จ๊ณ๋ฅผ ์งํํฉ๋๋ค.
- ๊ฒ์ถ๋ ๊ฐ์ฒด์ ์ขํ๋ (300, 300) ํฌ๊ธฐ์ ์ด๋ฏธ์ง ๊ธฐ์ค์ผ๋ก ๋์ด ์์ผ๋ฏ๋ก ์๋ณธ ์ด๋ฏธ์ง ํฌ๊ธฐ (cols, rows)์ ๋ง๊ฒ ๋ณํํฉ๋๋ค.
- labels_to_names ๋์ ๋๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ํด๋์ค ID๋ฅผ ํด๋์ค๋ช ์ผ๋ก ๋ณํํ๊ณ , ์ ๋ขฐ๋ ์ ์๋ฅผ ํฌํจํ ์บก์ ์ ์์ฑํฉ๋๋ค.
- cv2.rectangle ํจ์๋ฅผ ์ฌ์ฉํ์ฌ draw_img ์ด๋ฏธ์ง์ ์ฌ๊ฐํ์ ๊ทธ๋ฆฌ๋ฉฐ, cv2.putText ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์บก์ ์ ์ด๋ฏธ์ง์ ์ถ๊ฐํฉ๋๋ค.
- ๋ง์ง๋ง์ผ๋ก, ์บก์ ๊ณผ ํด๋์ค ID๋ฅผ ์ถ๋ ฅํฉ๋๋ค. OpenCV๋ ๊ธฐ๋ณธ์ ์ผ๋ก BGR ํ์์ ์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ์ด๋ฅผ RGB ํ์์ผ๋ก ๋ณํํ ํ, plt.figure์ plt.imshow๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง๋ฅผ ์๊ฐํํฉ๋๋ค.
- ์ด ๊ณผ์ ์์ ์ด๋ฏธ์ง์๋ ๊ฐ ๊ฐ์ฒด์ ๊ฒฝ๊ณ ์์์ ์บก์ ์ด ๊ทธ๋ ค์ง๋ฉฐ, ์ด๋ฅผ matplotlib์ ์ฌ์ฉํ์ฌ ํ์ํฉ๋๋ค.
(1, 1, 100, 7)
person: 0.9696 1
person: 0.9660 1
person: 0.8916 1
person: 0.6298 1
car: 0.8609 3
car: 0.7223 3
car: 0.7184 3
car: 0.7095 3
car: 0.5949 3
car: 0.5511 3
<matplotlib.image.AxesImage at 0x7fda6c0c92b0>
๋จ์ผ ์ด๋ฏธ์ง์ Object Detection์ ํจ์๋ก ์์ฑ
์ด๋ฒ์๋ ๋จ์ผ ์ด๋ฏธ์ง์ Object Detection ๋ถ๋ถ์ ํจ์๋ก ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค.
import time
def get_detected_img(cv_net, img_array, score_threshold, use_copied_array=True, is_print=True):
rows = img_array.shape[0]
cols = img_array.shape[1]
draw_img = None
if use_copied_array:
draw_img = img_array.copy()
#draw_img = cv2.cvtColor(draw_img, cv2.COLOR_BGR2RGB)
else:
draw_img = img_array
cv_net.setInput(cv2.dnn.blobFromImage(img_array, size=(300, 300), swapRB=True, crop=False))
start = time.time()
cv_out = cv_net.forward()
green_color=(0, 255, 0)
red_color=(0, 0, 255)
# detected ๋ object๋ค์ iteration ํ๋ฉด์ ์ ๋ณด ์ถ์ถ
for detection in cv_out[0,0,:,:]:
score = float(detection[2])
class_id = int(detection[1])
# detected๋ object๋ค์ score๊ฐ 0.4 ์ด์๋ง ์ถ์ถ
if score > score_threshold:
# detected๋ object๋ค์ image ํฌ๊ธฐ๊ฐ (300, 300)์ผ๋ก scale๋ ๊ธฐ์ค์ผ๋ก ์์ธก๋์์ผ๋ฏ๋ก ๋ค์ ์๋ณธ ์ด๋ฏธ์ง ๋น์จ๋ก ๊ณ์ฐ
left = detection[3] * cols
top = detection[4] * rows
right = detection[5] * cols
bottom = detection[6] * rows
# labels_to_names ๋์
๋๋ฆฌ๋ก class_id๊ฐ์ ํด๋์ค๋ช
์ผ๋ก ๋ณ๊ฒฝ. opencv์์๋ class_id + 1๋ก ๋งคํํด์ผํจ.
caption = "{}: {:.4f}".format(labels_to_names[class_id], score)
#cv2.rectangle()์ ์ธ์๋ก ๋ค์ด์จ draw_img์ ์ฌ๊ฐํ์ ๊ทธ๋ฆผ. ์์น ์ธ์๋ ๋ฐ๋์ ์ ์ํ.
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.7, red_color, 2)
if is_print:
print('Detection ์ํ์๊ฐ:',round(time.time() - start, 2),"์ด")
return draw_img
- get_detected_img ํจ์๋ ์ ๋ ฅ ์ด๋ฏธ์ง(img_array)์์ ๊ฐ์ฒด๋ฅผ ๊ฒ์ถํ๊ณ , ๊ฒ์ถ๋ ๊ฐ์ฒด์ ๊ฒฝ๊ณ ์์์ ์บก์ ์ ์ด๋ฏธ์ง์ ๊ทธ๋ฆฝ๋๋ค. ํจ์๋ ๋ค์๊ณผ ๊ฐ์ ๋จ๊ณ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
- ๋จผ์ , ์ ๋ ฅ ์ด๋ฏธ์ง์ ํ(rows)๊ณผ ์ด(cols) ํฌ๊ธฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค. draw_img ๋ณ์๋ use_copied_array ์ธ์์ ๋ฐ๋ผ ์ ๋ ฅ ์ด๋ฏธ์ง์ ๋ณต์ฌ๋ณธ ๋๋ ์๋ณธ์ ์ ์ฅํฉ๋๋ค.
- cv_net.setInput ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง ๋ฐ์ดํฐ๋ฅผ ๋คํธ์ํฌ์ ์
๋ ฅ์ผ๋ก ์ค์ ํฉ๋๋ค.
- ์ด๋ ์ด๋ฏธ์ง๋ (300, 300) ํฌ๊ธฐ๋ก ๋ฆฌ์ฌ์ด์ฆ๋๊ณ , RGB ์ฑ๋ ์์๋ก ๋ณํ๋ฉ๋๋ค.
- ๊ฐ์ฒด ๊ฒ์ถ์ ์์ํ๊ธฐ ์ ์ ์์ ์๊ฐ์ ๊ธฐ๋กํ๊ณ , cv_net.forward() ํจ์๋ก ๊ฐ์ฒด ๊ฒ์ถ์ ์ํํฉ๋๋ค.
- ์ดํ cv_out ๋ฐฐ์ด์์ ๊ฒ์ถ๋ ๊ฐ์ฒด๋ค์ ๋ฐ๋ณตํ์ฌ ๊ฐ๊ฐ์ ์ ๋ณด๋ฅผ ์ถ์ถํฉ๋๋ค.
- ์ ๋ขฐ๋ ์ ์(score)๊ฐ score_threshold ์ด์์ธ ๊ฐ์ฒด๋ง์ ์ฒ๋ฆฌํฉ๋๋ค.
- ๊ฒ์ถ๋ ๊ฐ์ฒด์ ์ขํ๋ ์๋ณธ ์ด๋ฏธ์ง ํฌ๊ธฐ์ ๋ง๊ฒ ๋ณํ๋ฉ๋๋ค.
- labels_to_names ๋์ ๋๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ํด๋์ค ID๋ฅผ ํด๋์ค๋ช ์ผ๋ก ๋ณํํ๊ณ , ์ ๋ขฐ๋ ์ ์๋ฅผ ํฌํจํ ์บก์ ์ ์์ฑํฉ๋๋ค.
- cv2.rectangle ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ถ๋ ๊ฐ์ฒด์ ์์น์ ์ฌ๊ฐํ์ ๊ทธ๋ฆฌ๊ณ , cv2.putText ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์บก์ ์ ์ด๋ฏธ์ง์ ์ถ๊ฐํฉ๋๋ค.
- ๋ง์ง๋ง์ผ๋ก, is_print๊ฐ True์ธ ๊ฒฝ์ฐ ๊ฐ์ฒด ๊ฒ์ถ ์ํ ์๊ฐ์ ์ถ๋ ฅํฉ๋๋ค. ๋ณํ๋ ์ด๋ฏธ์ง๋ฅผ ๋ฐํํ๋ฉฐ, ์ด ์ด๋ฏธ์ง๋ ๊ฒ์ถ๋ ๊ฐ์ฒด์ ๊ฒฝ๊ณ ์์์ ์บก์ ์ด ํฌํจ๋ ์ํ์ ๋๋ค.
# image ๋ก๋
img = cv2.imread('../../data/image/john_wick01.jpg')
#coco dataset ํด๋์ค๋ช
๋งคํ
# tensorflow inference ๋ชจ๋ธ ๋ก๋ฉ
cv_net = cv2.dnn.readNetFromTensorflow('./pretrained/ssd_inception_v2_coco_2017_11_17/frozen_inference_graph.pb',
'./pretrained/ssd_inception_v2_coco_2017_11_17/graph.pbtxt')
# Object Detetion ์ํ ํ ์๊ฐํ
draw_img = get_detected_img(cv_net, img, score_threshold=0.4, use_copied_array=True, is_print=True)
img_rgb = cv2.cvtColor(draw_img, cv2.COLOR_BGR2RGB)
plt.figure(figsize=(12, 12))
plt.imshow(img_rgb)
๋ฐ์ํ
'๐ Computer Vision' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[CV] OpenCV DNN ํจํค์ง & SSD ๊ธฐ๋ฐ Object Detection ์ํ (0) | 2024.07.10 |
---|---|
[CV] SSD - Single Shot (Multibox) Detector (0) | 2024.07.07 |
[CV] OpenCV๋ก Object Detection ๊ตฌํํ๊ธฐ (Part.1) (0) | 2024.06.02 |
[CV] Faster R-CNN (Faster Region-based Convolutional Neural Network) (0) | 2024.05.29 |
[CV] Fast R-CNN (Fast Region-based Convolutional Neural Network) (0) | 2024.05.27 |