DEEP.I - Lab

오프라인 공간의 지능화를 꿈꾸는 딥아이 연구실입니다.

Python/Python

[YOLO] Python과 OpenCV를 이용한 실시간 객체 탐지 알고리즘 구현

Jongwon Kim 2020. 6. 26. 17:39
반응형

 

Window 아나콘다 가상 환경을 활용하여 YOLO Object Detection을 구동해보았습니다. 일반적으로 쓰이는 프레임워크 Darknet이 아닌OpenCV 내장 함수를 이용하였기에 복잡한 설치나 환경 설정이 필요하지 않습니다.

출처 :  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 프레임워크들의 장단점을 구분하고 있습니다.

1. Darknet : 원개발자가 만든 YOLO만을 위한 프레임워크

장점 : 연산이 빠르고, GPU와 CPU 연산 모두 지원

단점 : Linux 환경에서만 지원 (복잡하긴 하지만 환경변수, VS 등을 통해 구현은 가능합니다.)

2. DarkFlow : Darknet의 텐서플로우 버전

장점 : 연산이 빠르고, GPU와 CPU 연산 모두 지원 + 모든 OS 지원

단점 : 복잡한 설치조건

3. OpenCV : 내장 함수를 통한 YOLO 구현

장점 : 간단한 설치

단점 : CPU 연산만 지원

1~2번의 경우, OpenCV, Tensorflow, Python 등의 버전에 상당히 종속적이다보니 한가지만 틀어져도 실행 자체가 안되는 경우가 많습니다. Nvida TX2 인공지능 보드를 활용한 프로젝트에서 이때문에 정말 힘들었었죠.. 10FPS 이상의 실시간 탐지 성능을 원하시는것이 아니거나, 학습된 가중치를 간단하게 테스트를 하시는 경우라면 본문에서 다룰 3번의 방법을 추천드립니다.

1. 가상환경 생성
 
conda create -n py36yolo python=3.6
 
원활한 구동을 위해 순정 상태의 가상 환경을 생성합니다. 저는 python은 3.6버전을 기준으로 하였습니다. 설치 옵션이 뜨면 y를 눌러 설치를 진행해줍니다.

2. OpenCV 3.4 설치
 
conda install opencv=3.4
 
순정 상태에서 설치하면 필요 라이브러리까지 모두 설치해줍니다.
 
3. YOLO 파라미터 다운로드 (weight 파일, cfg 파일, names 파일)
 
다운로드 링크 : https://pjreddie.com/darknet/yolo/
 
링크를 스크롤하여 내려가시면 Performance on the COCO Dataset에 대한 객체 탐지 성능 비교표가 있습니다. 이곳에서 자신에게 맞는 모델의 Weights 파일Cfg 파일을 python이 실행될 경로로 받으시면 됩니다. CPU에게 가혹할것같아 저는 가벼운 Tiny YOLO로 테스트하였습니다. cfg 파일 학습된 클래스 정보가 포함된 names 파일은 첨부된 파일을 다운받으셔도 됩니다. 
 
 
 
4. MainActivity.py - 파라미터 불러오기

import cv2
import numpy as np

# 웹캠 신호 받기
VideoSignal = cv2.VideoCapture(0)
# YOLO 가중치 파일과 CFG 파일 로드
YOLO_net = cv2.dnn.readNet("yolov2-tiny.weights","yolov2-tiny.cfg")

# YOLO NETWORK 재구성
classes = []
with open("yolo.names", "r") as f:
classes = [line.strip() for line in f.readlines()]
layer_names = YOLO_net.getLayerNames()
output_layers = [layer_names[i[0] - 1] for i in YOLO_net.getUnconnectedOutLayers()]

 

5. MainActivity.py - 객체 검출 단계

while True:
    # 웹캠 프레임
    ret, frame = VideoSignal.read()
    h, w, c = frame.shape

    # YOLO 입력
    blob = cv2.dnn.blobFromImage(frame, 0.00392, (416, 416), (0, 0, 0),      True, crop=False)
    YOLO_net.setInput(blob)
    outs = YOLO_net.forward(output_layers)

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

 

6. MainActivity.py - NMS를 통한 최종 검출 정보 최적화

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 # 검출기의 경계상자 좌표는 0 ~ 1로 정규화되어있으므로 다시 전처리
center_x = int(detection[0] * w)
center_y = int(detection[1] * h)
dw = int(detection[2] * w)
dh = int(detection[3] * h)
# Rectangle coordinate
x = int(center_x - dw / 2)
y = int(center_y - dh / 2)
boxes.append([x, y, dw, dh])
confidences.append(float(confidence))
class_ids.append(class_id)

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

 

7. MainActivity.py - 최종적으로 도출된 경계상자와 클래스 정보를 이미지에 투영

for i in range(len(boxes)):
if i in indexes:
x, y, w, h = boxes[i]
label = str(classes[class_ids[i]])
score = confidences[i]

# 경계상자와 클래스 정보 투영
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 5)
cv2.putText(frame, label, (x, y - 20), cv2.FONT_ITALIC, 0.5, (255, 255, 255), 1)


cv2.imshow("YOLOv2", frame)
# 100ms 마다 영상 갱신
if cv2.waitKey(100) > 0:
break

 

8. MainActivity.py - 전체 코드


import cv2
import numpy as np

# 웹캠 신호 받기
VideoSignal = cv2.VideoCapture(0)
# YOLO 가중치 파일과 CFG 파일 로드
YOLO_net = cv2.dnn.readNet("yolov2-tiny.weights","yolov2-tiny.cfg")

# YOLO NETWORK 재구성
classes = []
with open("yolo.names", "r") as f:
classes = [line.strip() for line in f.readlines()]
layer_names = YOLO_net.getLayerNames()
output_layers = [layer_names[i[0] - 1] for i in YOLO_net.getUnconnectedOutLayers()]

while True:
# 웹캠 프레임
ret, frame = VideoSignal.read()
h, w, c = frame.shape

# YOLO 입력
blob = cv2.dnn.blobFromImage(frame, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
YOLO_net.setInput(blob)
outs = YOLO_net.forward(output_layers)

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] * w)
center_y = int(detection[1] * h)
dw = int(detection[2] * w)
dh = int(detection[3] * h)
# Rectangle coordinate
x = int(center_x - dw / 2)
y = int(center_y - dh / 2)
boxes.append([x, y, dw, dh])
confidences.append(float(confidence))
class_ids.append(class_id)

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


for i in range(len(boxes)):
if i in indexes:
x, y, w, h = boxes[i]
label = str(classes[class_ids[i]])
score = confidences[i]

# 경계상자와 클래스 정보 이미지에 입력
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 5)
cv2.putText(frame, label, (x, y - 20), cv2.FONT_ITALIC, 0.5, (255, 255, 255), 1)

cv2.imshow("YOLOv3", frame)

if cv2.waitKey(100) > 0:
break

 

9. 실행결과 

한국정보화진흥원에서 제공하는 이상행동 CCTV 데이터셋으로 테스트를 진행하였습니다. CPU 연산이지만 가벼운 YOLO를 사용하여 5~10FPS 정도의 성능을 보였지만 기본 학습 가중치를 이용하여 검출율이 높지는 않았습니다.

 

# 머신러닝 프로젝트 제작, 상담 및 컨설팅  / 머신러닝 접목 졸업작품 컨설팅

# 데이터 가공, 수집, 라벨링 작업 / C, 파이썬 프로그램 제작

# email : contact@deep-i.ai

# site : www.deep-i.ai

반응형