4 분 소요

기본적인 Yolo 사용해보기

기본 Yolo 설치

Yolo V5 설치 YoloV5은 2020년에 새로 개발되었다. 기존 Yolo와 다르게 PyTorch 프레임 워크를 기반으로했따. YoloV4의 상위호환은 아니지만 장점이 있다.

다양한 모델 여러 플렛폼이용 듣등

최근에 YoloV7까지 있는데 천천이 알아보고

! Darknet 및 PyTorch 같은 플렛폼 공부가 필요해 보인다.

1단계 개발 환경 설치

# Tested with torch==1.11. 
# Tested with opencv-contrib-python versions [4.5.4.58 to 4.6.0.66].
!pip install torch==1.11 torchvision  --user
!pip install opencv-contrib-python==4.6.0.66  --user

2단계 Git코드 가져오기

한글 언어 제외 경로로 설정

!git clone https://github.com/ultralytics/yolov5
%cd yolov5
!pip install -r requirements.txt
!pip install onnx

3단계 모델 다운로드

%cd models
!wget https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5n.pt -nv
!wget https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5s.pt -nv
!wget https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5m.pt -nv
!wget https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5l.pt -nv
!wget https://github.com/ultralytics/yolov5/releases/download/v6.1/yolov5x.pt -nv
%cd ..

4단계 ONNX 추출


# The default input size is 640x640.
!python export.py --weights models/yolov5n.pt --include onnx
!python export.py --weights models/yolov5s.pt --include onnx
!python export.py --weights models/yolov5m.pt --include onnx
!python export.py --weights models/yolov5l.pt --include onnx
!python export.py --weights models/yolov5x.pt --include onnx

팁 만약

UnicodeDecodeError: ‘cp949’ codec can’t decode byte 0xf0 in position 9: illegal multibyte sequence 에러 발생시 requirements.txt 열어서 디코딩을 Ansi로 변경

5단계 샘플 이미지 가져오기

https://www.dropbox.com/s/hhx3pbacs7rixid/street.jpg?dl=1 -O street.jpg https://www.dropbox.com/s/wb5nkwuml526bqa/coco.names?dl=1 -O coco.names #객체 저장 이름

라이브러리 호출

import numpy as np
import cv2
import sys
import requests
from os import path

import matplotlib.pyplot as plt
%matplotlib inline

import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (15.0,15.0)
plt.rcParams['image.cmap'] = 'gray'
plt.rcParams['axes.titlesize'] = 14
plt.rcParams['axes.labelsize'] = 14

YoloV5는 네모 상자에 예측하기 결과를 애축한다. 모든 예측은 점수에 따라 정해진다 .

# Constants.
INPUT_WIDTH = 640             # Width of network's input image, larger is slower but more accurate
INPUT_HEIGHT = 640            # Height of network's input image, larger is slower but more accurate
SCORE_THRESHOLD = 0.5         # Class score threshold, accepts only if score is above the threshold.
NMS_THRESHOLD = 0.45          # Non-maximum suppression threshold, higher values result in duplicate boxes per object 
CONFIDENCE_THRESHOLD = 0.45   # Confidence threshold, high values filter out low confidence detections

# Text parameters.
FONT_FACE = cv2.FONT_HERSHEY_SIMPLEX
FONT_SCALE = 2.5
THICKNESS = 4

# Colors
BLACK  = (0,0,0)
BLUE   = (255,178,50)
YELLOW = (0,255,255)
RED = (0,0,255)
WHITE = (255,255,255)

전처리 함수

def pre_process(input_image, net):
    # Create a 4D blob from a frame.
    blob = cv2.dnn.blobFromImage(input_image, 1/255, (INPUT_WIDTH, INPUT_HEIGHT), [0,0,0], 1, crop=False)

    # Sets the input to the network.
    net.setInput(blob)

    # Runs the forward pass to get output of the output layers.
    output_layers = net.getUnconnectedOutLayersNames()
    outputs = net.forward(output_layers)
    # print(outputs[0].shape)

    return outputs

결과 출력

def post_process(input_image, outputs):
    # Lists to hold respective values while unwrapping.
    class_ids = []
    confidences = []
    boxes = []

    # Rows.
    rows = outputs[0].shape[1]

    image_height, image_width = input_image.shape[:2]

    # Resizing factor.
    x_factor = image_width / INPUT_WIDTH
    y_factor =  image_height / INPUT_HEIGHT

    # Iterate through 25200 detections.
    for r in range(rows):
        row = outputs[0][0][r]
        confidence = row[4]

        # Discard bad detections and continue.
        if confidence >= CONFIDENCE_THRESHOLD:
            classes_scores = row[5:]

            # Get the index of max class score.
            class_id = np.argmax(classes_scores)

            #  Continue if the class score is above threshold.
            if (classes_scores[class_id] > SCORE_THRESHOLD):
                confidences.append(confidence)
                class_ids.append(class_id)

                cx, cy, w, h = row[0], row[1], row[2], row[3]

                left = int((cx - w/2) * x_factor)
                top = int((cy - h/2) * y_factor)
                width = int(w * x_factor)
                height = int(h * y_factor)

                box = np.array([left, top, width, height])
                boxes.append(box)

    # Perform non maximum suppression to eliminate redundant overlapping boxes with
    # lower confidences.
    indices = cv2.dnn.NMSBoxes(boxes, confidences, CONFIDENCE_THRESHOLD, NMS_THRESHOLD)
    for i in indices:
        box = boxes[i]
        left = box[0]
        top = box[1]
        width = box[2]
        height = box[3]
        cv2.rectangle(input_image, (left, top), (left + width, top + height), BLUE, 4*THICKNESS)
        label = "{}:{:.2f}".format(classes[class_ids[i]], confidences[i])
        draw_label(input_image, label, left, top)

    return input_image

라벨 그리기 함수

def draw_label(input_image, label, left, top):
    """Draw text onto image at location."""
    
    # Get text size.
    text_size = cv2.getTextSize(label, FONT_FACE, FONT_SCALE, THICKNESS)
    dim, baseline = text_size[0], text_size[1]
    # Use text size to create a BLACK rectangle. 
    cv2.rectangle(input_image, (left, top), (left + dim[0], top + dim[1] + baseline), BLACK, cv2.FILLED);
    # Display text inside the rectangle.
    cv2.putText(input_image, label, (left, top + dim[1]), FONT_FACE, FONT_SCALE, YELLOW, THICKNESS, cv2.LINE_AA)

효과 넣기 넣기

def put_efficiency(input_img, net):
  t, _ = net.getPerfProfile()
  label = 'Inference time: %.2f ms' % (t * 1000.0 / cv2.getTickFrequency())
  print(label)
  cv2.putText(input_img, label, (20, 80), FONT_FACE, FONT_SCALE, RED, THICKNESS, cv2.LINE_AA)

이미지 넣기

frame = cv2.imread('street.jpg')

classesFile = "coco.names"
classes = None
with open(classesFile, 'rt') as f:
  classes = f.read().rstrip('\n').split('\n')

plt.imshow(frame[...,::-1]);

결과

YOLOv5 nano

# Load the network.
modelWeights = "models/yolov5n.onnx"
net = cv2.dnn.readNet(modelWeights)

# Process image.
detections = pre_process(frame, net)
img = post_process(frame.copy(), detections)

# Put efficiency information.
put_efficiency(img, net)

plt.imshow(img[...,::-1]);

YOLOv5 small

# Load the network.
modelWeights = "models/yolov5s.onnx"
net = cv2.dnn.readNet(modelWeights)

# Process image.
detections = pre_process(frame, net)
img = post_process(frame.copy(), detections)

# Put efficiency information.
put_efficiency(img, net)

plt.imshow(img[...,::-1]);

YOLOv5 Medium

# Load the network.
modelWeights = "models/yolov5m.onnx"
net = cv2.dnn.readNet(modelWeights)

# Process image.
detections = pre_process(frame, net)
img = post_process(frame.copy(), detections)

# Put efficiency information.
put_efficiency(img, net)

plt.imshow(img[...,::-1]);

YOLOv5 Large

# Load the network.
modelWeights = "models/yolov5l.onnx"
net = cv2.dnn.readNet(modelWeights)

# Process image.
detections = pre_process(frame, net)
img = post_process(frame.copy(), detections)

# Put efficiency information.
put_efficiency(img, net)

plt.imshow(img[...,::-1]);

자료 출처

https://bong-sik.tistory.com/16

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

댓글남기기