Window 아나콘다 가상 환경을 활용하여 YOLO Object Detection을 구동해보았습니다. 일반적으로 쓰이는 프레임워크 Darknet이 아닌OpenCV 내장 함수를 이용하였기에 복잡한 설치나 환경 설정이 필요하지 않습니다.
출처 : https://pysource.com/2019/06/27/yolo-object-detection-using-opencv-with-python/
자료를 공개한 개발자는 다음과 같이 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번의 방법을 추천드립니다.
conda create -n py36yolo python=3.6
conda install opencv=3.4
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
'Python > Python' 카테고리의 다른 글
[Python] PyTicToc 파이썬에서 경과 시간 간편하게 측정하기 (0) | 2020.11.25 |
---|---|
[Python] 파이썬 OpenCV를 이용한 얼굴 인식 (1) | 2020.11.05 |
[Python] configparser를 이용하여 config (설정값 ini 파일) 관리하기 (0) | 2020.11.01 |
[Python] OpenCV 실시간으로 영상의 Frame Rate (FPS) 확인하기 (1) | 2020.10.23 |
[Python] OpenCV를 이용한 영상 재생과 Frame Rate (FPS) 조절 (1) | 2020.07.12 |