6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Darknet/YOLOv3-Tinyに新しい物体を学習させる。 〜インストールから学習して推論するまで〜 [環境構築編]

Last updated at Posted at 2020-04-15

概要

YOLOv3-Tinyを使った転移学習をしてみたので備忘録的にメモ
学習の際にはGPUを使用する。
また、CUDA/cuDNN等のインストールは事前に行っているものとし、ここでは割愛する。
内容は[環境構築編]、[学習編]、[推論編]の3つの記事に分ける予定

環境

OS:Ubuntu 18.04
GPU:RTX2060

darknetをインストールする。

まずはYOLOを動かすためのdarknetをインストールする。

git clone https://github.com/pjreddie/darknet.git
cd darknet

MakeFileを以下の様に編集する。

GPU=1
CUDNN=1
CUDNN_HALF=1
OPENCV=1
AVX=0
OPENMP=0
LIBSO=1

それぞれがどういう設定か説明すると
GPU/CUDNN:GPUを使った推論、学習を有効にするかどうか
CUDNN_HALF/LIBSO:Tensorコアを使った推論の高速化を有効。学習自体の速度はおそらく上がらない。 ※GPUによってTensorコアが使えない場合は0とする
OPENCV:OpenCVを使うか否か(大体OpenCVを使うことが多いので1で良い)

更にMakeFileのARCHをコメントアウトする

\# ARCH= -gencode arch=compute_30,code=sm_30 \
      -gencode arch=compute_35,code=sm_35 \
      -gencode arch=compute_50,code=[sm_50,compute_50] \
      -gencode arch=compute_52,code=[sm_52,compute_52] \
	  -gencode arch=compute_61,code=[sm_61,compute_61]

そして今回はRTX2060なのでコメントを参照して適切なARCHを有効にする

# GeForce RTX 2080 Ti, RTX 2080, RTX 2070, Quadro RTX 8000, Quadro RTX 6000, Quadro RTX 5000, Tesla T4, XNOR Tensor Cores
ARCH= -gencode arch=compute_75,code=[sm_75,compute_75]

最後にmakeを実行

make -j 8

darknetを使って推論する場合、重み係数ファイルが必要となる。
今回はYOLOv3-Tinyを使用する。

wget https://pjreddie.com/media/files/yolov3-tiny.weights

動作確認

新たにyolo_tiny.pyを作成し、以下を記載

yolo_tiny.py
from ctypes import *
import math
import random
import os
import cv2
import numpy as np
import time
import darknet

import time, sys
# import Queue

def convertBack(x, y, w, h):
    xmin = int(round(x - (w / 2)))
    xmax = int(round(x + (w / 2)))
    ymin = int(round(y - (h / 2)))
    ymax = int(round(y + (h / 2)))
    return xmin, ymin, xmax, ymax

def cvDrawBoxes(detections, img):
    for detection in detections:
        x, y, w, h = detection[2][0],\
            detection[2][1],\
            detection[2][2],\
            detection[2][3]
        xmin, ymin, xmax, ymax = convertBack(
            float(x), float(y), float(w), float(h))
        pt1 = (xmin, ymin)
        pt2 = (xmax, ymax)
        cv2.rectangle(img, pt1, pt2, (255, 255, 0), 4)
        cv2.putText(img,
                    detection[0].decode() +
                    " [" + str(round(detection[1] * 100, 2)) + "]",
                    (pt1[0], pt1[1] - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
                    [255, 255, 0], 2)
    return img

netMain = None
metaMain = None
altNames = None

class fpsWithTick(object):
    def __init__(self):
        self._count     = 0
        self._oldCount  = 0
        self._freq      = 1000 / cv2.getTickFrequency()
        self._startTime = cv2.getTickCount()
    def get(self):
        nowTime         = cv2.getTickCount()
        diffTime        = (nowTime - self._startTime) * self._freq
        self._startTime = nowTime
        fps             = (self._count - self._oldCount) / (diffTime / 1000.0)
        self._oldCount  = self._count
        self._count     += 1
        fpsRounded      = round(fps, 1)
        return fpsRounded

def YOLO():
    global metaMain, netMain, altNames
    configPath = "./cfg/yolov3-tiny.cfg"  
    weightPath = "./yolov3-tiny.weights" 
    metaPath = "./cfg/coco.data"
    if not os.path.exists(configPath):
        raise ValueError("Invalid config path `" +
                         os.path.abspath(configPath)+"`")
    if not os.path.exists(weightPath):
        raise ValueError("Invalid weight path `" +
                         os.path.abspath(weightPath)+"`")
    if not os.path.exists(metaPath):
        raise ValueError("Invalid data file path `" +
                         os.path.abspath(metaPath)+"`")
    if netMain is None:
        netMain = darknet.load_net_custom(configPath.encode(
            "ascii"), weightPath.encode("ascii"), 0, 1)  # batch size = 1
    if metaMain is None:
        metaMain = darknet.load_meta(metaPath.encode("ascii"))
    if altNames is None:
        try:
            with open(metaPath) as metaFH:
                metaContents = metaFH.read()
                import re
                match = re.search("names *= *(.*)$", metaContents,
                                  re.IGNORECASE | re.MULTILINE)
                if match:
                    result = match.group(1)
                else:
                    result = None
                try:
                    if os.path.exists(result):
                        with open(result) as namesFH:
                            namesList = namesFH.read().strip().split("\n")
                            altNames = [x.strip() for x in namesList]
                except TypeError:
                    pass
        except Exception:
            pass
    out = cv2.VideoWriter(
        "output.avi", cv2.VideoWriter_fourcc(*"MJPG"), 10.0,
        (darknet.network_width(netMain), darknet.network_height(netMain)))
    print("Starting the YOLO loop...")

    # Create an image we reuse for each detect
    darknet_image = darknet.make_image(darknet.network_width(netMain),
                                    darknet.network_height(netMain),3)
    fps = fpsWithTick()  # 初期化
    cap = cv2.VideoCapture(0)
                              
    while True:
        prev_time = time.time()
        ret, frame_read = cap.read()
        if not ret :
            break
        height, width, channels = frame_read.shape[:3]
        frame_rgb = cv2.cvtColor(frame_read, cv2.COLOR_BGR2RGB)
        frame_resized = cv2.resize(frame_rgb,
                                (darknet.network_width(netMain),
                                    darknet.network_height(netMain)),
                                interpolation=cv2.INTER_LINEAR)
        # frame_resized = frame_rgb
        darknet.copy_image_from_bytes(darknet_image,frame_resized.tobytes())
        detections = darknet.detect_image(netMain, metaMain, darknet_image, thresh=0.3)
        image = cvDrawBoxes(detections, frame_resized)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        cv2.imshow('YOLOv3-Tiny', image)
        out.write(image)
        fps_time = fps.get()  # FPSを計算する
        print(f"FPS:{fps_time}")
        cv2.waitKey(3)

if __name__ == "__main__":
    YOLO()

そして最後にWebカメラを接続し、以下を実行して物体検出がされていれば問題なくインストールが完了

python yolo-tiny.py

Webカメラがない場合は好き動画をyolo-tiny.pyと同一のディレクトリに入れ、cap = cv2.VideoCapture(0)の引数を動画のファイル名にすれば良い

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?