A A
[CV] OpenCV์—์„œ YOLO๋ฅผ ์ด์šฉํ•œ Object Detection Part.2
์ •์‹ ์ด ์—†์–ด์„œ ์ด์–ด์„œ ์“ฐ๋Š”๊ฑธ ๊นŒ๋จน์—ˆ๋„ค์š”.. ์—ด์‹ฌํžˆ ์จ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค ใ… 
# ํ˜„์žฌ ๋””๋ ‰ํ† ๋ฆฌ๋Š” /content์ด๋ฉฐ ์ด ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์‹ค์Šต์ฝ”๋“œ์™€ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์šด๋กœ๋“œ ํ•ฉ๋‹ˆ๋‹ค. 
!pwd
!rm -rf DLCV
!git clone https://github.com/chulminkw/DLCV.git
# DLCV ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ Download๋˜๊ณ  DLCV ๋ฐ‘์— Detection๊ณผ Segmentation ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธ
!ls -lia 
!ls -lia DLCV

OpenCV Darknet YOLO๋ฅผ ์ด์šฉํ•˜์—ฌ image & ์˜์ƒ Object Detection

  • ์—ฌ๊ธฐ์„  YOLO์™€ tiny-yolo๋ฅผ ์ด์šฉํ•˜์—ฌ Object Detection์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
import cv2
import matplotlib.pyplot as plt
import os
%matplotlib inline

# ์ฝ”๋žฉ ๋ฒ„์ „์€ default_dir ์€ /content/DLCV๋กœ ์ง€์ •ํ•˜๊ณ  os.path.join()์œผ๋กœ ์ƒ์„ธ ํŒŒ์ผ/๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. 
default_dir = '/content/DLCV'
img = cv2.imread(os.path.join(default_dir, '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)
image shape: (633, 806, 3)
<matplotlib.image.AxesImage at 0x7cb8db20ff10>

๋ฐ์ดํ„ฐ์…‹์„ ํ™•์ธํ›„, Darknet Yolo์‚ฌ์ดํŠธ์—์„œ coco๋กœ ํ•™์Šต๋œ Inference๋ชจ๋ธ์™€ ํ™˜๊ฒฝํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œ ๋ฐ›์€ ํ›„ ์ด๋ฅผ ์ด์šฉํ•ด OpenCV์—์„œ Inference ๋ชจ๋ธ์„ ์ƒ์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

!rm -rf /content/DLCV/Detection/yolo//pretrained
!mkdir /content/DLCV/Detection/yolo/pretrained
# pretrained ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ ํ•ฉ๋‹ˆ๋‹ค. 
%cd /content/DLCV/Detection/yolo
!ls

### coco ๋ฐ์ดํ„ฐ ์„ธํŠธ๋กœ pretrained ๋œ yolo weight ํŒŒ์ผ๊ณผ config ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ 
%cd /content/DLCV/Detection/yolo/pretrained
!echo "##### downloading pretrained yolo/tiny-yolo weight file and config file"
!wget https://pjreddie.com/media/files/yolov3.weights
!wget https://github.com/pjreddie/darknet/blob/master/cfg/yolov3.cfg?raw=true -O ./yolov3.cfg

!wget https://pjreddie.com/media/files/yolov3-tiny.weights
!wget wget https://github.com/pjreddie/darknet/blob/master/cfg/yolov3-tiny.cfg?raw=true -O ./yolov3-tiny.cfg

!echo "##### check out pretrained yolo files"
!ls /content/DLCV/Detection/yolo/pretrained

readNetFromDarknet(config weightํŒŒ์ผ)์„ ์ด์šฉํ•˜์—ฌ yolo inference network ๋ชจ๋ธ๋กœ๋”ฉ

import os
 
#CUR_DIR = os.path.abspath('.')
# ์ฝ”๋žฉ ๋ฒ„์ „์€ ์•„๋ž˜ ์ฝ”๋“œ ์‚ฌ์šฉ 
CUR_DIR = '/content/DLCV/Detection/yolo'
weights_path = os.path.join(CUR_DIR, 'pretrained/yolov3.weights')
config_path =  os.path.join(CUR_DIR, 'pretrained/yolov3.cfg')
#config ํŒŒ์ผ ์ธ์ž๊ฐ€ ๋จผ์ € ์˜ด. 
cv_net_yolo = cv2.dnn.readNetFromDarknet(config_path, weights_path)

COCO Class id์™€ Class๋ช… Mapping

labels_to_names_seq๋Š” class id๊ฐ€ 0~79๊นŒ์ง€์ž…๋‹ˆ๋‹ค.
- OpenCV DNN Darknet YOLO Model์„ Loadํ•ฉ๋‹ˆ๋‹ค.
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' }
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๊ฐœ์˜ Scale Output Layer์—์„œ ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ ์ถ”์ถœ

# YOLO ๋„คํŠธ์›Œํฌ์—์„œ ๋ชจ๋“  ๋ ˆ์ด์–ด ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜ด
layer_names = cv_net_yolo.getLayerNames()

# ์ถœ๋ ฅ ๋ ˆ์ด์–ด์˜ ์ธ๋ฑ์Šค๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ YOLOv3์˜ ์ถœ๋ ฅ ๋ ˆ์ด์–ด ์ด๋ฆ„์„ ์ถ”์ถœ
outlayer_names = [layer_names[i - 1] for i in cv_net_yolo.getUnconnectedOutLayers()]

# ์ถœ๋ ฅ ๋ ˆ์ด์–ด ์ด๋ฆ„์„ ์ถœ๋ ฅ (13x13, 26x26, 52x52 grid์—์„œ ํƒ์ง€๋œ ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ ˆ์ด์–ด๋“ค)
print('output_layer name:', outlayer_names)

# ๋กœ๋”ฉ๋œ YOLOv3 ๋ชจ๋ธ์€ 416x416 ํฌ๊ธฐ๋ฅผ ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•จ. 
# ์ด๋ฏธ์ง€๋ฅผ 416x416์œผ๋กœ ํฌ๊ธฐ ๋ณ€๊ฒฝํ•˜๊ณ  BGR ์ฑ„๋„์„ RGB๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋„คํŠธ์›Œํฌ์— ์ž…๋ ฅํ•˜๊ธฐ ์œ„ํ•œ blob ์ƒ์„ฑ
cv_net_yolo.setInput(cv2.dnn.blobFromImage(
    img,               # ์›๋ณธ ์ด๋ฏธ์ง€
    scalefactor=1/255.0, # ํ”ฝ์…€ ๊ฐ’์„ 0~1 ๋ฒ”์œ„๋กœ ์ •๊ทœํ™” (255๋กœ ๋‚˜๋ˆ”)
    size=(416, 416),   # YOLOv3์˜ ์ž…๋ ฅ ํฌ๊ธฐ (416x416)
    swapRB=True,       # BGR ์ฑ„๋„์„ RGB๋กœ ๋ณ€ํ™˜
    crop=False         # ์ด๋ฏธ์ง€๋ฅผ ์ž๋ฅด์ง€ ์•Š๊ณ  ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ
))

# YOLO ๋„คํŠธ์›Œํฌ์—์„œ ์ง€์ •ํ•œ ์ถœ๋ ฅ ๋ ˆ์ด์–ด๋“ค์—์„œ ๊ฐ์ฒด ํƒ์ง€๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜
cv_outs = cv_net_yolo.forward(outlayer_names)

# ํƒ์ง€๋œ ๊ฐ์ฒด์˜ ๊ฒฝ๊ณ„ ์ƒ์ž(Bounding Box)๋ฅผ ๊ทธ๋ฆฌ๊ธฐ ์œ„ํ•œ ์ƒ‰์ƒ (๋…น์ƒ‰)
green_color = (0, 255, 0)

# ๊ฒฝ๊ณ„ ์ƒ์ž ์œ„์— ํ‘œ์‹œ๋  ์บก์…˜(๊ฐ์ฒด ์ด๋ฆ„ ๋ฐ ํ™•๋ฅ )์„ ์œ„ํ•œ ๊ธ€์ž์ƒ‰ (๋นจ๊ฐ„์ƒ‰)
red_color = (0, 0, 255)

# Result: output_layer name: ['yolo_82', 'yolo_94', 'yolo_106']

YOLO ๋„คํŠธ์›Œํฌ์—์„œ ์ถœ๋ ฅ ๋ ˆ์ด์–ด ์ด๋ฆ„์„ ์ถ”์ถœ

  • cv_net_yolo.getLayerNames(): ๋„คํŠธ์›Œํฌ์˜ ๋ชจ๋“  ๋ ˆ์ด์–ด ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. YOLOv3 ๋ชจ๋ธ์€ ์—ฌ๋Ÿฌ ๋ ˆ์ด์–ด๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๊ณ , ๊ฐ ๋ ˆ์ด์–ด๋Š” CNN(Convolutional Neural Network) ๊ณ„์ธต์ž…๋‹ˆ๋‹ค.
  • cv_net_yolo.getUnconnectedOutLayers(): ๋„คํŠธ์›Œํฌ์—์„œ ์ถœ๋ ฅ ๋ ˆ์ด์–ด์˜ ์ธ๋ฑ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. YOLOv3์—์„œ๋Š” 3๊ฐœ์˜ ์ถœ๋ ฅ ๋ ˆ์ด์–ด(13x13, 26x26, 52x52 grid)๊ฐ€ ์กด์žฌํ•˜๋ฉฐ, ์ด ๋ ˆ์ด์–ด๋“ค์—์„œ ๊ฐ์ฒด ํƒ์ง€๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • outlayer_names: YOLO ๋ชจ๋ธ์—์„œ ์ถœ๋ ฅ ๋ ˆ์ด์–ด๋“ค๋งŒ ์ถ”์ถœํ•œ ๋ฆฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค. ํƒ์ง€ ๊ฒฐ๊ณผ๋ฅผ ์ด ๋ ˆ์ด์–ด๋“ค์—์„œ ์–ป์Šต๋‹ˆ๋‹ค.

 

YOLOv3 ๋ชจ๋ธ์— ์ž…๋ ฅ ์ด๋ฏธ์ง€ ์„ค์ •

cv2.dnn.blobFromImage: ์ด๋ฏธ์ง€๋ฅผ ๋„คํŠธ์›Œํฌ์— ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•์‹(blob)์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์—์„œ ์—ฌ๋Ÿฌ ์„ค์ •์ด ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค:

  • scalefactor=1/255.0: ์ด๋ฏธ์ง€์˜ ํ”ฝ์…€ ๊ฐ’์„ 255๋กœ ๋‚˜๋ˆ„์–ด 0~1 ๋ฒ”์œ„๋กœ ์ •๊ทœํ™”ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์„ ํ†ตํ•ด YOLO ๋ชจ๋ธ์ด ํ•™์Šตํ•œ ๋ฐ์ดํ„ฐ์™€ ์ž…๋ ฅ๊ฐ’์„ ๋งž์ถฅ๋‹ˆ๋‹ค.
  • size=(416, 416): ์ž…๋ ฅ ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ๋ฅผ 416x416 ํ”ฝ์…€๋กœ ๋ฆฌ์‚ฌ์ด์ฆˆํ•ฉ๋‹ˆ๋‹ค. YOLOv3๋Š” 416x416 ํฌ๊ธฐ์˜ ์ด๋ฏธ์ง€๋ฅผ ํ•™์Šตํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ž…๋ ฅ ํฌ๊ธฐ๋ฅผ ๋งž์ถ”์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • swapRB=True: OpenCV๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ BGR ํ˜•์‹์˜ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ, YOLO๋Š” RGB ํ˜•์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ BGR์—์„œ RGB๋กœ ์ฑ„๋„์„ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • crop=False: ์ด๋ฏธ์ง€๋ฅผ ์ž๋ฅด์ง€ ์•Š๊ณ  ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

Object Detection ์ˆ˜ํ–‰

  • cv_net_yolo.forward(outlayer_names): YOLO ๋„คํŠธ์›Œํฌ์˜ ์ถœ๋ ฅ ๋ ˆ์ด์–ด์—์„œ ๊ฐ์ฒด ํƒ์ง€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค. outlayer_names๋Š” ์•ž์—์„œ ๊ตฌํ•œ ์ถœ๋ ฅ ๋ ˆ์ด์–ด๋“ค์ด๋ฉฐ, ์—ฌ๊ธฐ์„œ ๊ฐ ๊ฐ์ฒด์˜ ์œ„์น˜, ํฌ๊ธฐ, ๊ทธ๋ฆฌ๊ณ  ๊ฐ์ฒด ๋ถ„๋ฅ˜์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.
  • cv_outs: YOLOv3๊ฐ€ ์ถ”์ถœํ•œ ๊ฐ์ฒด ํƒ์ง€ ๊ฒฐ๊ณผ๊ฐ€ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.
output_layer name: ['yolo_82', 'yolo_94', 'yolo_106']


3๊ฐœ์˜ Scale Output Layer์—์„œ Object Detection ์ •๋ณด๋ฅผ ๋ชจ๋‘ ์ˆ˜์ง‘

Center, Width, Height ์ขŒํ‘œ๋Š” ๋ชจ๋‘ ์ขŒ์ƒ๋‹จ, ์šฐํ•˜๋‹จ ์ขŒํ‘œ๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.
import numpy as np

# ์›๋ณธ ์ด๋ฏธ์ง€๋ฅผ YOLO ๋„คํŠธ์›Œํฌ์— ์ž…๋ ฅํ•  ๋•Œ๋Š” (416, 416)์œผ๋กœ ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•จ.
# ๋„คํŠธ์›Œํฌ๊ฐ€ ์˜ˆ์ธกํ•œ bounding box ์ขŒํ‘œ๋Š” ์ด ํฌ๊ธฐ ๊ธฐ์ค€์œผ๋กœ ๊ณ„์‚ฐ๋˜๋ฏ€๋กœ, ์›๋ณธ ์ด๋ฏธ์ง€ ํฌ๊ธฐ์™€ ๋งž์ถ”๊ธฐ ์œ„ํ•ด ์›๋ณธ ์ด๋ฏธ์ง€์˜ shape ์ •๋ณด ํ•„์š”.
rows = img.shape[0]  # ์›๋ณธ ์ด๋ฏธ์ง€์˜ ๋†’์ด
cols = img.shape[1]  # ์›๋ณธ ์ด๋ฏธ์ง€์˜ ๋„ˆ๋น„

# Confidence(์‹ ๋ขฐ๋„)์™€ NMS(Non-Maximum Suppression) ์ž„๊ณ„๊ฐ’ ์„ค์ •
conf_threshold = 0.5  # confidence threshold (ํƒ์ง€๋œ ๊ฐ์ฒด์˜ ์‹ ๋ขฐ๋„ ์ตœ์†Œ๊ฐ’)
nms_threshold = 0.4   # Non-Maximum Suppression threshold (์ค‘๋ณต๋œ ๋ฐ•์Šค๋ฅผ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•œ ์ž„๊ณ„๊ฐ’)

# ํƒ์ง€๋œ ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ €์žฅํ•  ๋ฆฌ์ŠคํŠธ
class_ids = []      # ํด๋ž˜์Šค ID๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฆฌ์ŠคํŠธ
confidences = []    # ์‹ ๋ขฐ๋„๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฆฌ์ŠคํŠธ
boxes = []          # bounding box ์ขŒํ‘œ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฆฌ์ŠคํŠธ

# YOLO ๋„คํŠธ์›Œํฌ์—์„œ ๋ฐ˜ํ™˜๋œ 3๊ฐœ์˜ output layer์— ๋Œ€ํ•ด ํƒ์ง€๋œ ๊ฐ์ฒด ์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜๊ณ  ์‹œ๊ฐํ™”
for ix, output in enumerate(cv_outs):
    print('output shape:', output.shape)  # ๊ฐ output layer์˜ shape ์ถœ๋ ฅ (ํƒ์ง€๋œ ๊ฐ์ฒด์˜ ์ˆ˜์™€ ์†์„ฑ ํฌ๊ธฐ)
    
    # ๊ฐ output layer์—์„œ ํƒ์ง€๋œ ๊ฐ์ฒด๋ณ„๋กœ ์ •๋ณด๋ฅผ ์ถ”์ถœ
    for jx, detection in enumerate(output):
        # detection ๋ฐฐ์—ด์˜ 6๋ฒˆ์งธ ์š”์†Œ๋ถ€ํ„ฐ๋Š” ํด๋ž˜์Šค๋ณ„ ์ ์ˆ˜(class score)๋“ค์ด ์ €์žฅ๋˜์–ด ์žˆ์Œ (์•ž์˜ 5๊ฐœ๋Š” bounding box ์ •๋ณด)
        scores = detection[5:]
        # ๊ฐ€์žฅ ๋†’์€ ์ ์ˆ˜๋ฅผ ๊ฐ€์ง„ ์ธ๋ฑ์Šค(class ID)๋ฅผ ์ฐพ์Œ
        class_id = np.argmax(scores)
        # ํ•ด๋‹น ํด๋ž˜์Šค์˜ confidence(์‹ ๋ขฐ๋„) ๊ฐ’์„ ์ถ”์ถœ
        confidence = scores[class_id]

        # confidence๊ฐ€ conf_threshold๋ณด๋‹ค ๋†’์€ ๊ฐ์ฒด๋งŒ ์ฒ˜๋ฆฌ (ํƒ์ง€ ์‹ ๋ขฐ๋„๊ฐ€ ๋‚ฎ์€ ๊ฐ์ฒด๋Š” ๋ฌด์‹œ)
        if confidence > conf_threshold:
            print('ix:', ix, 'jx:', jx, 'class_id', class_id, 'confidence:', confidence)
            
            # detection ๋ฐฐ์—ด์˜ ์•ž๋ถ€๋ถ„์€ ์ค‘์‹ฌ ์ขŒํ‘œ(x, y)์™€ ๋„ˆ๋น„(width), ๋†’์ด(height)๋ฅผ ํฌํ•จํ•จ
            # YOLO๋Š” ์ขŒ์ƒ๋‹จ์ด๋‚˜ ์šฐํ•˜๋‹จ ์ขŒํ‘œ๊ฐ€ ์•„๋‹ˆ๋ผ ์ค‘์‹ฌ ์ขŒํ‘œ์™€ ํฌ๊ธฐ๋ฅผ ๋ฐ˜ํ™˜ํ•จ
            # ์ด ๊ฐ’์„ ์›๋ณธ ์ด๋ฏธ์ง€์— ๋งž๊ฒŒ ๋น„์œจ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ขŒ์ƒ๋‹จ๊ณผ ์šฐํ•˜๋‹จ ์ขŒํ‘œ๋ฅผ ๊ณ„์‚ฐ
            center_x = int(detection[0] * cols)  # ํƒ์ง€๋œ ๊ฐ์ฒด์˜ ์ค‘์‹ฌ x ์ขŒํ‘œ (์›๋ณธ ์ด๋ฏธ์ง€ ํฌ๊ธฐ์— ๋งž๊ฒŒ ์กฐ์ •)
            center_y = int(detection[1] * rows)  # ํƒ์ง€๋œ ๊ฐ์ฒด์˜ ์ค‘์‹ฌ y ์ขŒํ‘œ (์›๋ณธ ์ด๋ฏธ์ง€ ํฌ๊ธฐ์— ๋งž๊ฒŒ ์กฐ์ •)
            width = int(detection[2] * cols)     # ํƒ์ง€๋œ ๊ฐ์ฒด์˜ ๋„ˆ๋น„ (์›๋ณธ ์ด๋ฏธ์ง€ ํฌ๊ธฐ์— ๋งž๊ฒŒ ์กฐ์ •)
            height = int(detection[3] * rows)    # ํƒ์ง€๋œ ๊ฐ์ฒด์˜ ๋†’์ด (์›๋ณธ ์ด๋ฏธ์ง€ ํฌ๊ธฐ์— ๋งž๊ฒŒ ์กฐ์ •)
            
            # ์ขŒ์ƒ๋‹จ ์ขŒํ‘œ ๊ณ„์‚ฐ (์ค‘์‹ฌ ์ขŒํ‘œ์—์„œ ๋„ˆ๋น„์™€ ๋†’์ด์˜ ์ ˆ๋ฐ˜์„ ๋นผ์„œ ๊ตฌํ•จ)
            left = int(center_x - width / 2)
            top = int(center_y - height / 2)
            
            # ํƒ์ง€๋œ ๊ฐ์ฒด์˜ class ID, confidence, bounding box ์ขŒํ‘œ ์ •๋ณด๋ฅผ ์ €์žฅ
            class_ids.append(class_id)            # ํƒ์ง€๋œ ๊ฐ์ฒด์˜ ํด๋ž˜์Šค ID ์ €์žฅ
            confidences.append(float(confidence)) # ํƒ์ง€๋œ ๊ฐ์ฒด์˜ ์‹ ๋ขฐ๋„ ์ €์žฅ
            boxes.append([left, top, width, height])  # ํƒ์ง€๋œ ๊ฐ์ฒด์˜ bounding box ์ขŒํ‘œ ์ €์žฅ
output shape: (507, 85)
ix: 0 jx: 316 class_id 0 confidence: 0.8499539
ix: 0 jx: 319 class_id 0 confidence: 0.9317015
ix: 0 jx: 325 class_id 0 confidence: 0.7301026
ix: 0 jx: 328 class_id 0 confidence: 0.9623244
ix: 0 jx: 334 class_id 0 confidence: 0.9984485
ix: 0 jx: 337 class_id 0 confidence: 0.9833524
ix: 0 jx: 343 class_id 0 confidence: 0.9978433
ix: 0 jx: 346 class_id 0 confidence: 0.63752526
output shape: (2028, 85)
ix: 1 jx: 831 class_id 2 confidence: 0.81699777
ix: 1 jx: 832 class_id 2 confidence: 0.7153828
ix: 1 jx: 877 class_id 2 confidence: 0.78542227
ix: 1 jx: 955 class_id 2 confidence: 0.8472696
ix: 1 jx: 1199 class_id 0 confidence: 0.7259762
ix: 1 jx: 1202 class_id 0 confidence: 0.9635838
ix: 1 jx: 1259 class_id 0 confidence: 0.97018635
ix: 1 jx: 1262 class_id 0 confidence: 0.9877816
ix: 1 jx: 1277 class_id 0 confidence: 0.9924558
ix: 1 jx: 1280 class_id 0 confidence: 0.99840033
ix: 1 jx: 1295 class_id 0 confidence: 0.6916557
ix: 1 jx: 1313 class_id 0 confidence: 0.9205802
ix: 1 jx: 1337 class_id 0 confidence: 0.5387825
ix: 1 jx: 1340 class_id 0 confidence: 0.6424068
ix: 1 jx: 1373 class_id 0 confidence: 0.57844293
ix: 1 jx: 1391 class_id 0 confidence: 0.89902174
output shape: (8112, 85)
ix: 2 jx: 2883 class_id 2 confidence: 0.9077373
ix: 2 jx: 2886 class_id 2 confidence: 0.63324577
ix: 2 jx: 2892 class_id 2 confidence: 0.6575013
ix: 2 jx: 3039 class_id 2 confidence: 0.8036038
ix: 2 jx: 3048 class_id 2 confidence: 0.94120145
ix: 2 jx: 3051 class_id 2 confidence: 0.61540514
ix: 2 jx: 3184 class_id 2 confidence: 0.95041007
ix: 2 jx: 3185 class_id 2 confidence: 0.8492525
ix: 2 jx: 3214 class_id 2 confidence: 0.9064125
ix: 2 jx: 3373 class_id 2 confidence: 0.68997973
ix: 2 jx: 3394 class_id 0 confidence: 0.7640699
  • scores = detection[5:]: detection ๋ฐฐ์—ด์—์„œ ์ฒซ 5๊ฐœ ์š”์†Œ๋Š” bounding box ์ •๋ณด์ด๊ณ , ๊ทธ ์ดํ›„๊ฐ€ ํด๋ž˜์Šค๋ณ„ ์ ์ˆ˜์ž…๋‹ˆ๋‹ค.
  • CoCO Dataset์œผ๋กœ Pre-Trained๋œ Model์—์„œ BoundingBox ์ •๋ณด๋ฅผ ์ถ”์ถœ์‹œ
    • Bounding Box ์ •๋ณด๋ฅผ 4๊ฐœ์˜ Box ์ขŒํ‘œ, 1๊ฐœ์˜ Object Score, ๊ทธ๋ฆฌ๊ณ  80๊ฐœ์˜ Class score(Coco๋Š” 80๊ฐœ์˜ Object Category์ž„)๋กœ ๊ตฌ์„ฑ๋œ ์ด 85๊ฐœ์˜ ์ •๋ณด ๊ตฌ์„ฑ์—์„œ ์ •๋ณด ์ถ”์ถœ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
    • Class id์™€ class score๋Š” ์ด 80๊ฐœ vector์—์„œ ๊ฐ€์žฅ ๋†’์€ ๊ฐ’์„ ๊ฐ€์ง€๋Š” ์œ„์น˜ ์ธ๋ฑ์Šค์™€ ๊ทธ ๊ฐ’์ž…๋‹ˆ๋‹ค.

NMS๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐ Output layer์—์„œ Detected๋œ Object์˜ ๊ฒน์น˜๋Š” Bounding box ์ œ์™ธ

NMS Filtering ์ด๋ผ๊ณ ๋„ ํ•ฉ๋‹ˆ๋‹ค.
conf_threshold = 0.5
nms_threshold = 0.4
idxs = cv2.dnn.NMSBoxes(boxes, confidences, conf_threshold, nms_threshold)

print(idxs)

# Result: [ 4 17  6 15 30 28 24 32 11  8 34 33 25 29]
  • NMSBoxes๋Š” ์•ž์—์„œ ๊ตฌํ•œ list boxes ์ž…๋‹ˆ๋‹ค.

NMS๋กœ ์ตœ์ข… filtering๋œ idxs๋ฅผ ์ด์šฉํ•˜์—ฌ boxes, classes, confidences์—์„œ ํ•ด๋‹นํ•˜๋Š” Object์ •๋ณด ์ถ”์ถœ & ์‹œ๊ฐํ™”

# ์›๋ณธ ์ด๋ฏธ์ง€๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ ์‚ฌ๊ฐํ˜•์„ ๊ทธ๋ฆด ์ด๋ฏธ์ง€ ๋ฐฐ์—ด ์ƒ์„ฑ
draw_img = img.copy()

# NMS๋กœ ํ•„ํ„ฐ๋ง๋œ ๊ฐ์ฒด๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ์—๋งŒ ์ฒ˜๋ฆฌ
if len(idxs) > 0:
    # ํ•„ํ„ฐ๋ง๋œ ๊ฐ์ฒด๋“ค์˜ ์ธ๋ฑ์Šค๋ฅผ ํ•˜๋‚˜์”ฉ ์ฒ˜๋ฆฌ
    for i in idxs.flatten():
        box = boxes[i]  # bounding box ์ขŒํ‘œ ์ถ”์ถœ
        left = box[0]   # ์ขŒ์ƒ๋‹จ x ์ขŒํ‘œ
        top = box[1]    # ์ขŒ์ƒ๋‹จ y ์ขŒํ‘œ
        width = box[2]  # ๋ฐ•์Šค์˜ ๋„ˆ๋น„
        height = box[3] # ๋ฐ•์Šค์˜ ๋†’์ด
        
        # ํด๋ž˜์Šค๋ช…๊ณผ ์‹ ๋ขฐ๋„๋ฅผ ํ…์ŠคํŠธ๋กœ ์ƒ์„ฑ
        caption = "{}: {:.4f}".format(labels_to_names_seq[class_ids[i]], confidences[i])
        
        # bounding box ๊ทธ๋ฆฌ๊ธฐ
        cv2.rectangle(draw_img, (int(left), int(top)), (int(left + width), int(top + height)), color=green_color, thickness=2)
        
        # ํด๋ž˜์Šค๋ช…๊ณผ ์‹ ๋ขฐ๋„ ํ…์ŠคํŠธ ๊ทธ๋ฆฌ๊ธฐ
        cv2.putText(draw_img, caption, (int(left), int(top - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, red_color, 1)
        
        # ํด๋ž˜์Šค๋ช…๊ณผ ์‹ ๋ขฐ๋„๋ฅผ ์ฝ˜์†”์— ์ถœ๋ ฅ
        print(caption)

# BGR ์ด๋ฏธ์ง€๋ฅผ RGB๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์‹œ๊ฐํ™”
img_rgb = cv2.cvtColor(draw_img, cv2.COLOR_BGR2RGB)

# ์ด๋ฏธ์ง€ ํฌ๊ธฐ์™€ ์‹œ๊ฐํ™”
plt.figure(figsize=(12, 12))
plt.imshow(img_rgb)

 

person: 0.9984
person: 0.9984
person: 0.9978
person: 0.9878
car: 0.9504
car: 0.9412
car: 0.9077
car: 0.9064
car: 0.8473
car: 0.8170
person: 0.7641
car: 0.6900
car: 0.6332
car: 0.6154
<matplotlib.image.AxesImage at 0x7c3250be2f20>

์ด๋ฏธ์ง€ ๋ณต์‚ฌ ๋ฐ ์ดˆ๊ธฐํ™”

  • draw_img = img.copy()๋Š” ์›๋ณธ ์ด๋ฏธ์ง€๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. OpenCV์˜ rectangle() ํ•จ์ˆ˜๋Š” ์ธ์ž๋กœ ๋„˜๊ฒจ์ค€ ์ด๋ฏธ์ง€์— ๋ฐ”๋กœ ์‚ฌ๊ฐํ˜•์„ ๊ทธ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์—, ์›๋ณธ ์ด๋ฏธ์ง€๋ฅผ ๋ณด์กดํ•˜๋ ค๊ณ  ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

NMS ํ•„ํ„ฐ๋ง๋œ ๊ฐ์ฒด ์ฒ˜๋ฆฌ

  • Non-Maximum Suppression(NMS)์€ ์—ฌ๋Ÿฌ ๊ฐ์ฒด ํƒ์ง€ ๊ฒฐ๊ณผ ์ค‘์—์„œ ๊ฐ€์žฅ ์‹ ๋ขฐ๋„๊ฐ€ ๋†’์€ ๊ฒƒ์„ ์„ ํƒํ•˜๊ณ , ๋‹ค๋ฅธ ์ค‘๋ณต๋œ bounding box๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค. NMS ๊ฒฐ๊ณผ๋กœ idxs ๋ฆฌ์ŠคํŠธ์—๋Š” ํ•„ํ„ฐ๋ง๋œ ๊ฐ์ฒด๋“ค์˜ ์ธ๋ฑ์Šค๋งŒ ๋‚จ์Šต๋‹ˆ๋‹ค.
  • if len(idxs) > 0:๋Š” ํƒ์ง€๋œ ๊ฐ์ฒด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

Bounding Box์™€ ํด๋ž˜์Šค๋ช…, ์‹ ๋ขฐ๋„ ํ‘œ์‹œ

  • for i in idxs.flatten():๋Š” ํ•„ํ„ฐ๋ง๋œ ์ธ๋ฑ์Šค๋ฅผ ํ•˜๋‚˜์”ฉ ๋ฐ˜๋ณต ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. flatten() ํ•จ์ˆ˜๋Š” 2์ฐจ์› ๋ฐฐ์—ด์„ 1์ฐจ์› ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฐ˜๋ณตํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.
  • boxes[i]๋ฅผ ํ†ตํ•ด ํƒ์ง€๋œ ๊ฐ์ฒด์˜ bounding box ์ขŒํ‘œ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ , ์ด ์ขŒํ‘œ๋Š” ์ขŒ์ƒ๋‹จ x, ์ขŒ์ƒ๋‹จ y, ๋„ˆ๋น„, ๋†’์ด๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
  • caption์€ ํƒ์ง€๋œ ๊ฐ์ฒด์˜ ํด๋ž˜์Šค๋ช…๊ณผ ์‹ ๋ขฐ๋„๋ฅผ ํฌํ•จํ•œ ๋ฌธ์ž์—ด๋กœ, ์ด๋ฅผ ์ด๋ฏธ์ง€์— ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Bounding Box ๊ทธ๋ฆฌ๊ธฐ

  • cv2.rectangle() ํ•จ์ˆ˜๋Š” ์ด๋ฏธ์ง€ ์œ„์— ์‚ฌ๊ฐํ˜•์„ ๊ทธ๋ฆฌ๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ขŒ์ƒ๋‹จ ์ขŒํ‘œ์™€ ์šฐํ•˜๋‹จ ์ขŒํ‘œ๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์•„ ๊ฒฝ๊ณ„ ์ƒ์ž๋ฅผ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค. ๊ฒฝ๊ณ„ ์ƒ์ž์˜ ์ƒ‰์ƒ์€ green_color๋กœ ์„ค์ •๋˜์–ด ์žˆ๊ณ , ๋‘๊ป˜๋Š” 2์ž…๋‹ˆ๋‹ค.

ํ…์ŠคํŠธ(ํด๋ž˜์Šค๋ช…, ์‹ ๋ขฐ๋„)ํ‘œ์‹œ

  • cv2.putText() ํ•จ์ˆ˜๋Š” ์ด๋ฏธ์ง€์— ํ…์ŠคํŠธ๋ฅผ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค. ํ…์ŠคํŠธ๋Š” ๊ฐ์ฒด์˜ ํด๋ž˜์Šค๋ช…๊ณผ ์‹ ๋ขฐ๋„๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ํ…์ŠคํŠธ ์œ„์น˜๋Š” bounding box์˜ ์ขŒ์ƒ๋‹จ ์ขŒํ‘œ ์œ„์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ๊ธ€๊ผด์€ OpenCV์˜ FONT_HERSHEY_SIMPLEX๊ฐ€ ์‚ฌ์šฉ๋˜๊ณ , ๊ธ€์ž ํฌ๊ธฐ์™€ ์ƒ‰์ƒ์ด ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

BGR์—์„œ RGB๋กœ ๋ณ€ํ™˜ ๋ฐ ์‹œ๊ฐํ™”

  • OpenCV๋Š” BGR ํ˜•์‹์˜ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ, matplotlib์—์„œ๋Š” RGB ํ˜•์‹์˜ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ cv2.cvtColor()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ BGR ์ด๋ฏธ์ง€๋ฅผ RGB๋กœ ๋ณ€ํ™˜ํ•œ ํ›„, plt.imshow()๋ฅผ ํ†ตํ•ด ์ด๋ฏธ์ง€๋ฅผ ํ™”๋ฉด์— ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€ ํฌ๊ธฐ ์กฐ์ • ๋ฐ ์ถœ๋ ฅ

  • plt.figure(figsize=(12, 12))๋Š” ์ถœ๋ ฅ๋  ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ๋ฅผ ์„ค์ •ํ•˜๋ฉฐ, 12x12์ธ์น˜๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. plt.imshow(img_rgb)๋ฅผ ์‚ฌ์šฉํ•ด ์ด๋ฏธ์ง€ ๊ฒฐ๊ณผ๋ฅผ ์‹œ๊ฐ์ ์œผ๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

๋‹จ์ผ image๋ฅผ YOLO๋กœ detectํ•˜๋Š” get_detected_img ํ•จ์ˆ˜ ์ƒ์„ฑ

def get_detected_img(cv_net, img_array, conf_threshold, nms_threshold, use_copied_array=True, is_print=True):
    
    # ์›๋ณธ ์ด๋ฏธ์ง€๋ฅผ ๋„คํŠธ์›์— ์ž…๋ ฅ์‹œ์—๋Š” (416, 416)๋กœ resize ํ•จ. 
    # ์ดํ›„ ๊ฒฐ๊ณผ๊ฐ€ ์ถœ๋ ฅ๋˜๋ฉด resize๋œ ์ด๋ฏธ์ง€ ๊ธฐ๋ฐ˜์œผ๋กœ bounding box ์œ„์น˜๊ฐ€ ์˜ˆ์ธก ๋˜๋ฏ€๋กœ ์ด๋ฅผ ๋‹ค์‹œ ์›๋ณตํ•˜๊ธฐ ์œ„ํ•ด ์›๋ณธ ์ด๋ฏธ์ง€ shape์ •๋ณด ํ•„์š”
    rows = img_array.shape[0]
    cols = img_array.shape[1]
    draw_img = None
    if use_copied_array:
        draw_img = img_array.copy()
    else:
        draw_img = img_array
    
    #์ „์ฒด Darknet layer์—์„œ 13x13 grid, 26x26, 52x52 grid์—์„œ detect๋œ Output layer๋งŒ filtering
    layer_names = cv_net.getLayerNames()
    try:
        output_layers = cv_net.getUnconnectedOutLayers()
        
        # ์ธ๋ฑ์Šค ๋ฆฌ์ŠคํŠธ์™€ ์ •์ˆ˜ ๋ฆฌ์ŠคํŠธ ๋ชจ๋‘ ์ฒ˜๋ฆฌ
        outlayer_names = [layer_names[i - 1] if isinstance(i, list) else layer_names[i - 1] for i in output_layers]
    except:
        # ์œ„์˜ ๋ฐฉ๋ฒ•์ด ์‹คํŒจํ•˜๋ฉด ์ด ๋Œ€์•ˆ ๋ฐฉ๋ฒ•์„ ์‹œ๋„
        output_layers = cv_net.getUnconnectedOutLayers().flatten()
        outlayer_names = [layer_names[i - 1] for i in output_layers]
    
    # ๋กœ๋”ฉํ•œ ๋ชจ๋ธ์€ Yolov3 416 x 416 ๋ชจ๋ธ์ž„. ์›๋ณธ ์ด๋ฏธ์ง€ ๋ฐฐ์—ด์„ ์‚ฌ์ด์ฆˆ (416, 416)์œผ๋กœ, BGR์„ RGB๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฐฐ์—ด ์ž…๋ ฅ
    cv_net.setInput(cv2.dnn.blobFromImage(img_array, scalefactor=1/255.0, size=(416, 416), swapRB=True, crop=False))
    start = time.time()
    # Object Detection ์ˆ˜ํ–‰ํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ cvOut์œผ๋กœ ๋ฐ˜ํ™˜ 
    cv_outs = cv_net.forward(outlayer_names)
    layerOutputs = cv_net.forward(outlayer_names)
    # bounding box์˜ ํ…Œ๋‘๋ฆฌ์™€ caption ๊ธ€์ž์ƒ‰ ์ง€์ •
    green_color=(0, 255, 0)
    red_color=(0, 0, 255)

    class_ids = []
    confidences = []
    boxes = []

    # 3๊ฐœ์˜ ๊ฐœ๋ณ„ output layer๋ณ„๋กœ Detect๋œ Object๋“ค์— ๋Œ€ํ•ด์„œ Detection ์ •๋ณด ์ถ”์ถœ ๋ฐ ์‹œ๊ฐํ™” 
    for ix, output in enumerate(cv_outs):
        # Detected๋œ Object๋ณ„ iteration
        for jx, detection in enumerate(output):
            scores = detection[5:]
            class_id = np.argmax(scores)
            confidence = scores[class_id]
            # confidence๊ฐ€ ์ง€์ •๋œ conf_threshold๋ณด๋‹ค ์ž‘์€ ๊ฐ’์€ ์ œ์™ธ 
            if confidence > conf_threshold:
                #print('ix:', ix, 'jx:', jx, 'class_id', class_id, 'confidence:', confidence)
                # detection์€ scale๋œ ์ขŒ์ƒ๋‹จ, ์šฐํ•˜๋‹จ ์ขŒํ‘œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, detection object์˜ ์ค‘์‹ฌ์ขŒํ‘œ์™€ ๋„ˆ๋น„/๋†’์ด๋ฅผ ๋ฐ˜ํ™˜
                # ์›๋ณธ ์ด๋ฏธ์ง€์— ๋งž๊ฒŒ scale ์ ์šฉ ๋ฐ ์ขŒ์ƒ๋‹จ, ์šฐํ•˜๋‹จ ์ขŒํ‘œ ๊ณ„์‚ฐ
                center_x = int(detection[0] * cols)
                center_y = int(detection[1] * rows)
                width = int(detection[2] * cols)
                height = int(detection[3] * rows)
                left = int(center_x - width / 2)
                top = int(center_y - height / 2)
                # 3๊ฐœ์˜ ๊ฐœ๋ณ„ output layer๋ณ„๋กœ Detect๋œ Object๋“ค์— ๋Œ€ํ•œ class id, confidence, ์ขŒํ‘œ์ •๋ณด๋ฅผ ๋ชจ๋‘ ์ˆ˜์ง‘
                class_ids.append(class_id)
                confidences.append(float(confidence))
                boxes.append([left, top, width, height])
    
    # NMS๋กœ ์ตœ์ข… filtering๋œ idxs๋ฅผ ์ด์šฉํ•˜์—ฌ boxes, classes, confidences์—์„œ ํ•ด๋‹นํ•˜๋Š” Object์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜๊ณ  ์‹œ๊ฐํ™”.
    idxs = cv2.dnn.NMSBoxes(boxes, confidences, conf_threshold, nms_threshold)
    if len(idxs) > 0:
        for i in idxs.flatten():
            box = boxes[i]
            left = box[0]
            top = box[1]
            width = box[2]
            height = box[3]
            # labels_to_names ๋”•์…”๋„ˆ๋ฆฌ๋กœ class_id๊ฐ’์„ ํด๋ž˜์Šค๋ช…์œผ๋กœ ๋ณ€๊ฒฝ. opencv์—์„œ๋Š” class_id + 1๋กœ ๋งคํ•‘ํ•ด์•ผํ•จ.
            caption = "{}: {:.4f}".format(labels_to_names_seq[class_ids[i]], confidences[i])
            #cv2.rectangle()์€ ์ธ์ž๋กœ ๋“ค์–ด์˜จ draw_img์— ์‚ฌ๊ฐํ˜•์„ ๊ทธ๋ฆผ. ์œ„์น˜ ์ธ์ž๋Š” ๋ฐ˜๋“œ์‹œ ์ •์ˆ˜ํ˜•.
            cv2.rectangle(draw_img, (int(left), int(top)), (int(left+width), int(top+height)), color=green_color, thickness=2)
            cv2.putText(draw_img, caption, (int(left), int(top - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, red_color, 1)

    if is_print:
        print('Detection ์ˆ˜ํ–‰์‹œ๊ฐ„:',round(time.time() - start, 2),"์ดˆ")
    return draw_img
  • ์ž…๋ ฅ ์ด๋ฏธ์ง€ ํฌ๊ธฐ ํ™•์ธ ๋ฐ ๋ณต์‚ฌ๋ณธ ์ƒ์„ฑ:
    • ํ•จ์ˆ˜๊ฐ€ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›๋Š” img_array์˜ ํฌ๊ธฐ ์ •๋ณด๋ฅผ ํ™•์ธํ•˜์—ฌ rows์™€ cols์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋‚˜์ค‘์— ๋„คํŠธ์›Œํฌ๊ฐ€ ์˜ˆ์ธกํ•œ bounding box ์ขŒํ‘œ๋ฅผ ์›๋ž˜ ์ด๋ฏธ์ง€ ํฌ๊ธฐ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
    • use_copied_array ํ”Œ๋ž˜๊ทธ์— ๋”ฐ๋ผ ์›๋ณธ ์ด๋ฏธ์ง€๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ• ์ง€, ์•„๋‹ˆ๋ฉด ๋ณต์‚ฌ๋ณธ์„ ์‚ฌ์šฉํ• ์ง€ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ๋ณต์‚ฌ๋ณธ์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ์›๋ณธ ์ด๋ฏธ์ง€๋ฅผ ๋ณด์กดํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค.
  • ์ถœ๋ ฅ ๋ ˆ์ด์–ด ํ•„ํ„ฐ๋ง:
    • YOLO ๋ชจ๋ธ์˜ ๋ชจ๋“  ๋ ˆ์ด์–ด ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜ค๊ณ , getUnconnectedOutLayers() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ถœ๋ ฅ ๋ ˆ์ด์–ด๋“ค๋งŒ ํ•„ํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค. YOLOv3๋Š” 3๊ฐœ์˜ ์ถœ๋ ฅ ๋ ˆ์ด์–ด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, ๊ฐ ๋ ˆ์ด์–ด๋Š” ๋‹ค๋ฅธ ํฌ๊ธฐ์˜ ๊ทธ๋ฆฌ๋“œ(13x13, 26x26, 52x52)์—์„œ ๊ฐ์ฒด๋ฅผ ํƒ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋ฏธ์ง€ ์ „์ฒ˜๋ฆฌ ๋ฐ ๋„คํŠธ์›Œํฌ ์ž…๋ ฅ:
    • ์ด๋ฏธ์ง€๋ฅผ YOLOv3 ๋ชจ๋ธ์ด ์š”๊ตฌํ•˜๋Š” ํฌ๊ธฐ(416x416)๋กœ ๋ฆฌ์‚ฌ์ด์ฆˆํ•˜๊ณ , OpenCV์˜ ๊ธฐ๋ณธ BGR ํ˜•์‹์—์„œ YOLO๊ฐ€ ์š”๊ตฌํ•˜๋Š” RGB ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ cv2.dnn.blobFromImage() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฒ˜๋ฆฌํ•œ ํ›„, ๋„คํŠธ์›Œํฌ์— ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐ์ฒด ํƒ์ง€ ์ˆ˜ํ–‰:
    • cv_net.forward() ํ•จ์ˆ˜๋Š” ๋„คํŠธ์›Œํฌ์˜ ์ถœ๋ ฅ ๋ ˆ์ด์–ด์—์„œ ๊ฐ์ฒด ํƒ์ง€ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์—๋Š” ๊ฐ ๊ฐ์ฒด์˜ ์ค‘์‹ฌ ์ขŒํ‘œ, ๋„ˆ๋น„, ๋†’์ด, ์‹ ๋ขฐ๋„ ๋ฐ ํด๋ž˜์Šค๋ณ„ ์ ์ˆ˜ ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํƒ์ง€ ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ:
    • ํƒ์ง€๋œ ๊ฐ์ฒด๋“ค์˜ ์‹ ๋ขฐ๋„์™€ ํด๋ž˜์Šค ID๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์œ ํšจํ•œ ๊ฐ์ฒด๋งŒ ํ•„ํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค. ์‹ ๋ขฐ๋„๊ฐ€ ์ง€์ •๋œ ์ž„๊ณ„๊ฐ’(conf_threshold)๋ณด๋‹ค ๋†’์€ ๊ฐ์ฒด๋งŒ ์œ ํšจํ•œ ๊ฐ์ฒด๋กœ ๊ฐ„์ฃผํ•ฉ๋‹ˆ๋‹ค.
    • ๊ฐ ํƒ์ง€ ๊ฒฐ๊ณผ์—์„œ ๊ฐ์ฒด์˜ ์ค‘์‹ฌ ์ขŒํ‘œ์™€ ํฌ๊ธฐ ์ •๋ณด๋ฅผ ์›๋ณธ ์ด๋ฏธ์ง€ ํฌ๊ธฐ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ bounding box ์ขŒํ‘œ๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.
  • Non-Maximum Suppression (NMS):
    • Non-Maximum Suppression(NMS)์„ ์‚ฌ์šฉํ•˜์—ฌ ์ค‘๋ณต๋œ bounding box๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. NMS๋Š” ์—ฌ๋Ÿฌ bounding box๊ฐ€ ๊ฒน์น  ๋•Œ, ์‹ ๋ขฐ๋„๊ฐ€ ๊ฐ€์žฅ ๋†’์€ ๋ฐ•์Šค๋ฅผ ๋‚จ๊ธฐ๊ณ  ๋‚˜๋จธ์ง€๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค.
  • Bounding Box์™€ ํ…์ŠคํŠธ ์‹œ๊ฐํ™”:
    • NMS๋กœ ํ•„ํ„ฐ๋ง๋œ ๊ฐ์ฒด๋“ค์— ๋Œ€ํ•ด bounding box๋ฅผ ๊ทธ๋ฆฌ๊ณ , ํƒ์ง€๋œ ๊ฐ์ฒด์˜ ํด๋ž˜์Šค๋ช…๊ณผ ์‹ ๋ขฐ๋„๋ฅผ ์ด๋ฏธ์ง€์— ํ…์ŠคํŠธ๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. cv2.rectangle() ํ•จ์ˆ˜๋Š” bounding box๋ฅผ ๊ทธ๋ฆฌ๋Š” ์—ญํ• ์„ ํ•˜๊ณ , cv2.putText()๋Š” ํ…์ŠคํŠธ๋ฅผ ์ด๋ฏธ์ง€์— ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค.
  • ํƒ์ง€ ์‹œ๊ฐ„ ์ถœ๋ ฅ ๋ฐ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜:
    • ํƒ์ง€์— ๊ฑธ๋ฆฐ ์‹œ๊ฐ„์„ ์ถœ๋ ฅํ•˜๊ณ , bounding box์™€ ํด๋ž˜์Šค๋ช…์ด ๊ทธ๋ ค์ง„ ์ด๋ฏธ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import time


# image ๋กœ๋“œ 
default_dir = '/content/DLCV'
img = cv2.imread(os.path.join(default_dir, 'data/image/beatles01.jpg'))

#coco dataset ํด๋ž˜์Šค๋ช… ๋งคํ•‘

import os
#๊ฐ€๊ธ‰์  ์ ˆ๋Œ€ ๊ฒฝ๋กœ ์‚ฌ์šฉ. 
#CUR_DIR = os.path.abspath('.')
# ์ฝ”๋žฉ ๋ฒ„์ „์€ ์•„๋ž˜ ์ฝ”๋“œ ์‚ฌ์šฉ 
CUR_DIR = '/content/DLCV/Detection/yolo'
weights_path = os.path.join(CUR_DIR, 'pretrained/yolov3.weights')
config_path =  os.path.join(CUR_DIR, 'pretrained/yolov3.cfg')

# tensorflow inference ๋ชจ๋ธ ๋กœ๋”ฉ
cv_net_yolo = cv2.dnn.readNetFromDarknet(config_path, weights_path)
    
conf_threshold = 0.5
nms_threshold = 0.4
# Object Detetion ์ˆ˜ํ–‰ ํ›„ ์‹œ๊ฐํ™” 
draw_img = get_detected_img(cv_net_yolo, img, conf_threshold=conf_threshold, nms_threshold=nms_threshold, 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)
Detection ์ˆ˜ํ–‰์‹œ๊ฐ„: 4.44 ์ดˆ
<matplotlib.image.AxesImage at 0x7c3250b01c60>
  • SSD์— ๋น„ํ•ด์„  ๋Š๋ฆฌ์ง€๋งŒ Object Detection ์„ฑ๋Šฅ์€ ์ข‹์€๊ฑธ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


Video(์˜์ƒ) Object Detection

def do_detected_video(cv_net, input_path, output_path, conf_threshold, nms_threshold, is_print):
    
    # ์ž…๋ ฅ ๋น„๋””์˜ค ํŒŒ์ผ์„ ์ฝ๊ธฐ ์œ„ํ•ด VideoCapture ๊ฐ์ฒด ์ƒ์„ฑ
    cap = cv2.VideoCapture(input_path)

    # ๋น„๋””์˜ค ์ฝ”๋ฑ ์„ค์ • (XVID ์‚ฌ์šฉ)
    codec = cv2.VideoWriter_fourcc(*'XVID')

    # ์ž…๋ ฅ ๋น„๋””์˜ค์˜ ํฌ๊ธฐ์™€ FPS๋ฅผ ๊ฐ€์ ธ์˜ด
    vid_size = (round(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), round(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
    vid_fps = cap.get(cv2.CAP_PROP_FPS)

    # ์ถœ๋ ฅ ๋น„๋””์˜ค ํŒŒ์ผ์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ VideoWriter ๊ฐ์ฒด ์ƒ์„ฑ
    vid_writer = cv2.VideoWriter(output_path, codec, vid_fps, vid_size) 

    # ๋น„๋””์˜ค์˜ ์ด ํ”„๋ ˆ์ž„ ์ˆ˜ ๊ฐ€์ ธ์˜ค๊ธฐ
    frame_cnt = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    print('์ด Frame ๊ฐฏ์ˆ˜:', frame_cnt)

    # Bounding box์™€ ํ…์ŠคํŠธ์˜ ์ƒ‰์ƒ ์„ค์ •
    green_color = (0, 255, 0)  # Bounding box ์ƒ‰์ƒ (๋…น์ƒ‰)
    red_color = (0, 0, 255)    # ํ…์ŠคํŠธ ์ƒ‰์ƒ (๋นจ๊ฐ„์ƒ‰)

    # ๋น„๋””์˜ค์˜ ๋ชจ๋“  ํ”„๋ ˆ์ž„์„ ํ•˜๋‚˜์”ฉ ์ฒ˜๋ฆฌ
    while True:
        hasFrame, img_frame = cap.read()  # ๋น„๋””์˜ค์˜ ํ•œ ํ”„๋ ˆ์ž„์„ ์ฝ์–ด์˜ด
        if not hasFrame:
            print('๋” ์ด์ƒ ์ฒ˜๋ฆฌํ•  frame์ด ์—†์Šต๋‹ˆ๋‹ค.')
            break  # ํ”„๋ ˆ์ž„์„ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•˜๋ฉด ์ข…๋ฃŒ
        
        # YOLOv3๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด ํƒ์ง€ ์ˆ˜ํ–‰
        returned_frame = get_detected_img(cv_net, img_frame, conf_threshold=conf_threshold, nms_threshold=nms_threshold, \
                                          use_copied_array=False, is_print=is_print)
        
        # ํƒ์ง€ ๊ฒฐ๊ณผ๊ฐ€ ํฌํ•จ๋œ ํ”„๋ ˆ์ž„์„ ์ถœ๋ ฅ ๋น„๋””์˜ค์— ์ €์žฅ
        vid_writer.write(returned_frame)

    # ๋น„๋””์˜ค ํŒŒ์ผ ์ €์žฅ์„ ๋งˆ๋ฌด๋ฆฌ
    vid_writer.release()
    cap.release()
default_dir = '/content/DLCV'
do_detected_video(cv_net_yolo, os.path.join(default_dir, 'data/video/John_Wick_small.mp4'), 
                  os.path.join(default_dir, 'data/output/John_Wick_small_yolo01.avi'), conf_threshold,
                  nms_threshold, True)
  1. ์ž…๋ ฅ ๋น„๋””์˜ค ๋กœ๋“œ:
    • cv2.VideoCapture(input_path)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง€์ •๋œ ๋น„๋””์˜ค ํŒŒ์ผ์„ ์ฝ์Šต๋‹ˆ๋‹ค.
  2. ๋น„๋””์˜ค ์ถœ๋ ฅ ์„ค์ •:
    • cv2.VideoWriter๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ถœ๋ ฅ ๋น„๋””์˜ค ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅ ๋น„๋””์˜ค์˜ ํ•ด์ƒ๋„(vid_size)์™€ FPS(vid_fps)๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  3. ํ”„๋ ˆ์ž„ ๋ฐ˜๋ณต ์ฒ˜๋ฆฌ:
    • cap.read()๋ฅผ ํ†ตํ•ด ๋น„๋””์˜ค์—์„œ ํ”„๋ ˆ์ž„์„ ํ•˜๋‚˜์”ฉ ์ฝ์Šต๋‹ˆ๋‹ค.
    • ๊ฐ ํ”„๋ ˆ์ž„์— ๋Œ€ํ•ด get_detected_img() ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ YOLOv3๋ฅผ ์‚ฌ์šฉํ•œ ๊ฐ์ฒด ํƒ์ง€๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
    • ํƒ์ง€๋œ ๊ฐ์ฒด๊ฐ€ ํฌํ•จ๋œ ํ”„๋ ˆ์ž„์„ ์ถœ๋ ฅ ๋น„๋””์˜ค ํŒŒ์ผ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  4. ์ข…๋ฃŒ ์ฒ˜๋ฆฌ:
    • ๋” ์ด์ƒ ์ฒ˜๋ฆฌํ•  ํ”„๋ ˆ์ž„์ด ์—†์œผ๋ฉด ๋ฃจํ”„๋ฅผ ์ข…๋ฃŒํ•˜๊ณ , ๋น„๋””์˜ค ํŒŒ์ผ์„ ์ €์žฅํ•œ ํ›„ ์ž์›์„ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.

ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค๋ช…

  • cv_net: YOLOv3 ๋„คํŠธ์›Œํฌ (๋ชจ๋ธ).
  • input_path: ์ž…๋ ฅ ๋น„๋””์˜ค ํŒŒ์ผ ๊ฒฝ๋กœ.
  • output_path: ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•  ์ถœ๋ ฅ ๋น„๋””์˜ค ํŒŒ์ผ ๊ฒฝ๋กœ.
  • conf_threshold: ํƒ์ง€ ์‹ ๋ขฐ๋„ ์ž„๊ณ„๊ฐ’.
  • nms_threshold: Non-Maximum Suppression ์ž„๊ณ„๊ฐ’.
  • is_print: ํƒ์ง€ ๊ฒฐ๊ณผ ์ถœ๋ ฅ ์—ฌ๋ถ€ (ํƒ์ง€ ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ• ์ง€ ์—ฌ๋ถ€ ๊ฒฐ์ •).
## Object Detection ์ ์šฉ๋œ ์˜์ƒ ํŒŒ์ผ์„ google drive์—์„œ download ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด google drive๋ฅผ colab์— mount ์ˆ˜ํ–‰. 
import os, sys 
from google.colab import drive 

drive.mount('/content/gdrive')
## Object Detection ์ ์šฉ๋œ ์˜์ƒ ํŒŒ์ผ์„ google drive์—์„œ download ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 
## My Drive ๋””๋ ‰ํ† ๋ฆฌ ์ด๋ฆ„์— ๊ณต๋ž€์ด ์žˆ์œผ๋ฏ€๋กœ ' '๋กœ ๋ฌถ์Šต๋‹ˆ๋‹ค. 
!cp /content/DLCV/data/output/John_Wick_small_yolo01.avi '/content/gdrive/My Drive/John_Wick_small_yolo01.avi'

Tiny YOLO๋กœ Object Detection ์ˆ˜ํ–‰

tiny YOLO๋Š” ์ผ๋ฐ˜ YOLO๋ณด๋‹ค๋Š” ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง„๋‹ค๋Š” ํŠน์ง•์ด ์žˆ์Šต๋‹ˆ๋‹ค.
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import os
import time

# image ๋กœ๋“œ 
default_dir = '/content/DLCV'
img = cv2.imread(os.path.join(default_dir, 'data/image/beatles01.jpg'))

#coco dataset ํด๋ž˜์Šค๋ช… ๋งคํ•‘

import os
#๊ฐ€๊ธ‰์  ์ ˆ๋Œ€ ๊ฒฝ๋กœ ์‚ฌ์šฉ. 
#CUR_DIR = os.path.abspath('.')
# ์ฝ”๋žฉ ๋ฒ„์ „์€ ์•„๋ž˜ ์ฝ”๋“œ ์‚ฌ์šฉ 
CUR_DIR = '/content/DLCV/Detection/yolo'
weights_path = os.path.join(CUR_DIR, 'pretrained/yolov3-tiny.weights')
config_path =  os.path.join(CUR_DIR, 'pretrained/yolov3-tiny.cfg')

# tensorflow inference ๋ชจ๋ธ ๋กœ๋”ฉ
cv_net_yolo = cv2.dnn.readNetFromDarknet(config_path, weights_path)

#tiny yolo์˜ ๊ฒฝ์šฐ confidence๊ฐ€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋‚ฎ์Œ. 
conf_threshold = 0.3
nms_threshold = 0.4
# Object Detetion ์ˆ˜ํ–‰ ํ›„ ์‹œ๊ฐํ™” 
draw_img = get_detected_img(cv_net_yolo, img, conf_threshold=conf_threshold, nms_threshold=nms_threshold, 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)

Tiny YOLO๋กœ ์˜์ƒ Detection

default_dir = '/content/DLCV'

do_detected_video(cv_net_yolo, os.path.join(default_dir, 'data/video/John_Wick_small.mp4'),
                  os.path.join(default_dir, 'data/output/John_Wick_small_tiny_yolo01.avi'), conf_threshold,
                  nms_threshold, True)
## Object Detection ์ ์šฉ๋œ ์˜์ƒ ํŒŒ์ผ์„ google drive์—์„œ download ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 
## My Drive ๋””๋ ‰ํ† ๋ฆฌ ์ด๋ฆ„์— ๊ณต๋ž€์ด ์žˆ์œผ๋ฏ€๋กœ ' '๋กœ ๋ฌถ์Šต๋‹ˆ๋‹ค. 
!cp /content/DLCV/data/output/John_Wick_small_tiny_yolo01.avi '/content/gdrive/My Drive/John_Wick_small_tiny_yolo01.avi'