YOLO 사물인식 (Python, OpenCV)

2020. 12. 8. 17:12Dev

팀프로젝트를 진행하는 중 이미지처리 기술을 써야될 일이 생겼다.

YOLO 알고리즘이 빠르고 직관적이어서 사용해보았다.

 

사용 언어는 파이썬이고, 실행 프로그램은 주피터 노트북 - 아나콘다3를 사용했다.

 

https://pysource.com/2019/06/27/yolo-object-detection-using-opencv-with-python/

 

YOLO object detection using Opencv with Python - Pysource

We’re going to learn in this tutorial YOLO object detection. Yolo is a deep learning algorythm which came out on may 2016 and it became quickly so popular because it’s so fast compared with the previous deep learning algorythm. With yolo we can detect

pysource.com

영어 원문인 위 글을 참조했다.

 

 

YOLO 소개 홈페이지

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

 

YOLO: Real-Time Object Detection

YOLO: Real-Time Object Detection You only look once (YOLO) is a state-of-the-art, real-time object detection system. On a Pascal Titan X it processes images at 30 FPS and has a mAP of 57.9% on COCO test-dev. Comparison to Other Detectors YOLOv3 is extremel

pjreddie.com

OpenCV로 YOLO를 구현하기 위해서 위의 홈페이지에서 다운받아야 하는 파일이 두개 있다.

cfg와 weights 파일 두개를 다운받으면 된다.

참고한 본문에서는 yolov3.weights, yolov3.cfg 파일을 사용했다.

 

OpenCV로 YOLO를 사용하는 코드

pip install opencv-python

OpenCV가 설치되어 있지 않다면 설치하는 코드를 작성한다.

 

import cv2
import numpy as np

컴퓨터비전을 주로 처리하는 OpenCV와 행렬배열을 처리하는 라이브러리 numpy를 임포트 해준다.

 

# 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))

yolo를 불러오는 코드이다.

 

coco.names 파일은 yolo v2에 적용되어있는 파일을 그대로 이용하며 다크넷 홈페이지에서 구할 수 있다.

https://pjreddie.com/darknet/install/#cuda

 

Installing Darknet

Installing Darknet Darknet is easy to install with only two optional dependancies: OpenCV if you want a wider variety of supported image types. CUDA if you want GPU computation. Both are optional so lets start by just installing the base system. I've only

pjreddie.com

Installing The Base System 항목에 here를 눌러 git 페이지로 이동하고, data/coco.names를 다운받으면 된다.

 

yolo v3가 yolo v2를 기반으로 네트워크 약간의 부분만 수정되었기 때문에 yolo v2의 파일을 이용하는 것으로 보인다.

다크넷을 이용하면 수작업으로 파일을 다운받아야 하지 않아도 되지만 다크넷은 리눅스 os 위에서만 실행된다는 단점이 있다.

 

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

탐지를 진행할 이미지를 불러오는 코드이다.

두번째줄 resize를 진행하면 40% 비율로 사진이 줄어들고, 결과 사진을 출력할 때도 크기가 줄어든 채로 출력된다.

사진의 크기가 작으면 정확도가 떨어지지만 속도가 빠르고, 크기가 크면 정확도는 높지만 속도가 느리다.

프로젝트를 할 때는 정확도가 더 중요했기 때문에, 해당 코드를 주석처리하고 진행했다.

 

# 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)

객체를 탐지하는 코드이다.

여기까지 코드를 작성하면 객체 탐지가 완료된다.

 

# 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:
            # 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)

탐지된 객체에 바운딩 박스를 씌우는 코드로 추측된다.

confidence 값이 1에 가까우면 정확도가 높아지고, 0에 가까우면 정확도가 떨어지지만 검출되는 개체 수가 많아진다.

 

위의 검출 과정에서 동일한 객체에 생기는 바운딩 박스가 많아지기 때문에 이를 제거하기 위한 코드가 필요하다.

 

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

동일한 중복 박스들을 제거하는 코드이다.

 

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()

탐지, 검출을 거쳐서 나온 결과와 이미지를 화면에 출력하는 코드이다.

 

 

YOLO 탐지 결과

프로젝트가 가구 객체 검출에 관한 내용이었기 때문에 집안 내부의 가구들을 검출하는데 코드를 사용했다.

 

거실

거실에 있는 대표적인 가구인 소파, 티비, 테이블, 의자, 시계 등을 검출했다.

 

침실

침실에 있는 침대, 의자, 테이블, 컵을 검출했다.

침대는 일부분이 짤려있었는데도 검출이 됐다.

 

주방

냉장고, 오븐, 싱크대를 검출해냈다.

테이블이나 의자같은 경우, 사진의 1/4 가량도 나오지 않았지만 탐지가 가능했다.

 

'Dev' 카테고리의 다른 글

언리얼 엔진 - 퀵셀 브릿지 연동하는 방법  (0) 2020.08.04