๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๋”ฅ๋Ÿฌ๋‹๐Ÿค–/YOLO, Opencv ๐Ÿข

YOLO (You Only Look Once)

by @ENFJ 2022. 3. 23.

https://pjreddie.com/darknet/yolo/

- ๋น ๋ฅธ ์ถ”๋ก  ์†๋„์™€ ์ƒ๋‹นํ•œ ์ •ํ™•๋„๋ฅผ ์ž๋ž‘ํ•˜๋Š” ์˜ค๋ธŒ์ ํŠธ ๋””ํ…์…˜[๋ฌผ์ฒด ํƒ์ง€] ๋ชจ๋ธ 

 

๋ฌผ์ฒด ํƒ์ง€๋Š” ๊ฐ์ฒด์˜ ์œ„์น˜์™€ ํฌ๊ธฐ๋ฅผ ์˜ˆ์ธกํ•˜๋Š” ๋ฌธ์ œ์™€ ํ•ด๋‹น ๊ฐ์ฒด์˜ ํด๋ž˜์Šค๋ฅผ ๋ถ„๋ฅ˜ํ•˜๋Š” ๋ฌธ์ œ๋กœ ์„ธ๋ถ„ํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

๋ช‡ ๊ฐ€์ง€๋ฅผ ์ •๋ฆฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. YOLO๋Š” ๋”ฅ ๋Ÿฌ๋‹ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋ฏ€๋กœ ์ž์ฒด ์„ค์น˜๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์œผ๋ฉฐ ๋Œ€์‹  ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‹คํ–‰ํ• 

๋”ฅ ๋Ÿฌ๋‹ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

 


YOLO๋ฅผ ์„ค์น˜ํ•˜๋Š” ๋ฐฉ๋ฒ•?

YOLO์™€ ํ˜ธํ™˜๋˜๋Š” ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ์•Œ๋ ค์ง„ 3๊ฐ€์ง€ ํ”„๋ ˆ์ž„์›Œํฌ

 

  • Darknet : YOLO ๊ฐœ๋ฐœ์ž๊ฐ€ ๋งŒ๋“  ํ”„๋ ˆ์ž„์›Œํฌ๋กœ yolo๋ฅผ ์œ„ํ•ด ํŠน๋ณ„ํžˆ ์ œ์ž‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
    ์žฅ์ : ๋น ๋ฅด๊ณ , GPU ๋˜๋Š” CPU์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
    . ๋‹จ์ : Linux os์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

 

  • Darkflow: Tensorflow (๋˜ ๋‹ค๋ฅธ ๋”ฅ ๋Ÿฌ๋‹ ํ”„๋ ˆ์ž„์›Œํฌ)์— ๋Œ€ํ•œ darknet์˜ ์ ์‘์ž…๋‹ˆ๋‹ค.
    ์žฅ์ : ๋น ๋ฅด๊ณ , GPU ๋˜๋Š” CPU์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, Linux, Windows ๋ฐ Mac๊ณผ๋„ ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค.
    ๋‹จ์ : ํŠนํžˆ Windows์—์„œ ์„ค์น˜๊ฐ€ ๋งค์šฐ ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค.

 

  • Opencv: ๋˜ํ•œ opencv์—๋Š” YOLO์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” ๋”ฅ ๋Ÿฌ๋‹ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ opencv 3.4.2๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.
    ์žฅ์ : opencv๋ฅผ ์ œ์™ธํ•œ ์–ด๋–ค ๊ฒƒ๋„ ์„ค์น˜ํ•  ํ•„์š” ์—†์ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.
    ๋‹จ์ : CPU์—์„œ๋งŒ ์ž‘๋™ํ•˜๋ฏ€๋กœ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋น„๋””์˜ค๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์ •๋ง ๋น ๋ฅธ ์†๋„๋ฅผ ์–ป์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

Opencv์—์„œ YOLO๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

Opencv์™€ ํ•จ๊ป˜ YOLO๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ์ค‘์ ์„ ๋‘˜ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋ณต์žกํ•œ ์„ค์น˜๋ฅผ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๊ณ  ์ž‘๋™ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋น ๋ฅด๊ฒŒ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์ดˆ๋ณด์ž์—๊ฒŒ ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

 

๋จผ์ € Opencv ๋ฐ numpy ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐ€์ ธ์˜จ ๋‹ค์Œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.

ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

 
import cv2
import numpy as np

3๊ฐœ์˜ ํŒŒ์ผ์ด ํ•„์š”ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  • ๊ฐ€์ค‘์น˜ ํŒŒ์ผ: ํ•™์Šต๋œ ๋ชจ๋ธ, ๊ฐ์ฒด๋ฅผ ๊ฐ์ง€ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.
  • Cfg ํŒŒ์ผ : ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ๋ชจ๋“  ์„ค์ •์ด ์žˆ๋Š” ๊ตฌ์„ฑ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.
  • ํŒŒ์ผ ์ด๋ฆ„: ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐœ์ฒด์˜ ์ด๋ฆ„์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
# Load Yolo
net = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")
classes = []
with open("coco.names", "r") as f:
    classes = [line.strip() for line in f.readlines()]
layer_names = net.getLayerNames()
output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
colors = np.random.uniform(0, 255, size=(len(classes), 3))

๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ฐ์ฒด ๊ฐ์ง€๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ ค๋Š” ์ด๋ฏธ์ง€๋ฅผ ๋กœ๋“œํ•˜๊ณ  ๋„ˆ๋น„์™€ ๋†’์ด๋„ ์–ป์Šต๋‹ˆ๋‹ค.

# Loading image
img = cv2.imread("room_ser.jpg")
img = cv2.resize(img, None, fx=0.4, fy=0.4)
height, width, channels = img.shape

๋„คํŠธ์›Œํฌ์—์„œ ์ „์ฒด ์ด๋ฏธ์ง€๋ฅผ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋Š” ์—†์ง€๋งŒ ๋จผ์ € Blob์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. Blob ์ด๋ฏธ์ง€์—์„œ ๊ธฐ๋Šฅ์„ ์ถ”์ถœํ•˜๊ณ  ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. YOLO๋Š” ์„ธ ๊ฐ€์ง€ ํฌ๊ธฐ๋ฅผ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • 320×320 ํฌ๊ธฐ๊ฐ€ ์ž‘์•„์„œ ์ •ํ™•๋„๋Š” ๋–จ์–ด์ง€์ง€๋งŒ ์†๋„๋Š” ๋” ์ข‹์Šต๋‹ˆ๋‹ค.
  • 609×609 ํฌ๊ธฐ๊ฐ€ ์ปค์„œ ์ •ํ™•๋„๊ฐ€ ๋†’๊ณ  ์†๋„๊ฐ€ ๋Š๋ฆผ
  • 416×416 ์ค‘๊ฐ„์— ์žˆ๊ณ  ๋‘˜ ๋‹ค ์กฐ๊ธˆ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์—ฌ๊ธฐ์„œ Blob ์ด๋ž€?
Blob(Binary Large Object, ๋ธ”๋ž)์€ ์ด๋ฏธ์ง€, ์‚ฌ์šด๋“œ, ๋น„๋””์˜ค์™€ ๊ฐ™์€ ๋ฉ€ํ‹ฐ๋ฏธ๋””์–ด ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์•„๋ž˜ ์ฝ”๋“œ ๋งจ๋งˆ์ง€๋ง‰ ํ–‰ ์•„์›ƒ ์€ ํƒ์ง€ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. Outs๋Š” ํƒ์ง€๋œ ๊ฐœ์ฒด, ํ•ด๋‹น ์œ„์น˜ ๋ฐ ํƒ์ง€์— ๋Œ€ํ•œ ์‹ ๋ขฐ๋„์— ๋Œ€ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋Š” ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค.

# Detecting objects
blob = cv2.dnn.blobFromImage(img, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
net.setInput(blob)
outs = net.forward(output_layers)

์ด ์‹œ์ ์—์„œ ๊ฐ์ง€๊ฐ€ ์™„๋ฃŒ๋˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ํ™”๋ฉด์— ํ‘œ์‹œํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ ๋‹ค์Œ ์•„์›ƒ ๋ฐฐ์—ด์„ ๋ฐ˜๋ณตํ•˜๊ณ  ์‹ ๋ขฐ๋„๋ฅผ ๊ณ„์‚ฐํ•˜๊ณ  ์‹ ๋ขฐ๋„ ์ž„๊ณ„๊ฐ’์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

 

์•„๋ž˜ ์ฝ”๋“œ 32ํ–‰์—์„œ ์ž„๊ณ„๊ฐ’ ์‹ ๋ขฐ๋„๋ฅผ 0.5๋กœ ์„ค์ • ํ–ˆ์Šต๋‹ˆ๋‹ค . ๋” ํฌ๋ฉด ๊ฐœ์ฒด๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ฐ์ง€๋œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•˜๊ณ  ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค.
์ž„๊ณ„๊ฐ’์€ 0์—์„œ 1๊นŒ์ง€์ž…๋‹ˆ๋‹ค. 1์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ๊ฐ์ง€ ์ •ํ™•๋„๊ฐ€ ๋†’๊ณ  0์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ์ •ํ™•๋„๋Š” ๋‚ฎ์ง€๋งŒ ๊ฐ์ง€๋œ ๊ฐœ์ฒด์˜ ์ˆ˜๋„ ๋งŽ์Šต๋‹ˆ๋‹ค.

 

# Showing informations on the screen
class_ids = []
confidences = []
boxes = []
for out in outs:
    for detection in out:
        scores = detection[5:]
        class_id = np.argmax(scores)
        confidence = scores[class_id]
        if confidence > 0.5:    # 32ํ–‰์€ ์ด ๋ผ์ธ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค!!!!!!!!!!!!!!!!!!!!!!!!!
            # Object detected
            center_x = int(detection[0] * width)
            center_y = int(detection[1] * height)
            w = int(detection[2] * width)
            h = int(detection[3] * height)

            # Rectangle coordinates
            x = int(center_x - w / 2)
            y = int(center_y - h / 2)

            boxes.append([x, y, w, h])
            confidences.append(float(confidence))
            class_ids.append(class_id)

๊ฐ์ง€๋ฅผ ์ˆ˜ํ–‰ํ•  ๋•Œ ๋™์ผํ•œ ๊ฐ์ฒด์— ๋Œ€ํ•ด ๋” ๋งŽ์€ ์ƒ์ž๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ์ด "๋…ธ์ด์ฆˆ"๋ฅผ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋น„์ตœ๋Œ€ ์–ต์ œ ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)

๋งˆ์ง€๋ง‰์œผ๋กœ ๋ชจ๋“  ์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜์—ฌ ํ™”๋ฉด์— ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

  • Box : ๊ฐ์ง€๋œ ๋ฌผ์ฒด๋ฅผ ๋‘˜๋Ÿฌ์‹ธ๊ณ  ์žˆ๋Š” ์‚ฌ๊ฐํ˜•์˜ ์ขŒํ‘œ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
  • ๋ ˆ์ด๋ธ” : ๊ฐ์ง€๋œ ๊ฐœ์ฒด์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.
  • Confidence : 0์—์„œ 1๊นŒ์ง€์˜ ํƒ์ง€์— ๋Œ€ํ•œ ์‹ ๋ขฐ๋„์ž…๋‹ˆ๋‹ค.
font = cv2.FONT_HERSHEY_PLAIN
for i in range(len(boxes)):
    if i in indexes:
        x, y, w, h = boxes[i]
        label = str(classes[class_ids[i]])
        color = colors[i]
        cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)
        cv2.putText(img, label, (x, y + 30), font, 3, color, 3)


cv2.imshow("Image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

์ฐธ๊ณ : https://pysource.com/2019/06/27/yolo-object-detection-using-opencv-with-python/