物体検出でお馴染みのYOLOシリーズの最新版「YOLOv8」について、動かしながら試していきます。

YOLOv8は2023年1月に公開された最新バージョンであり、速度と精度の面で限界を押し広げています。

Google colabを使用して簡単に最新の物体検出モデルを実装することができますので、ぜひ最後までご覧ください。

これまでの投稿はこちら
第1回:YOLOv8を試してみる 〜導入からデモまで〜
第2回:推論の引数と座標とスコアの出力
第3回:YOLOv8でセグメンテーションを試してみる
第4回:YOLOv8における推論結果と座標について
第5回:マスク着用をリアルタイムに判定 〜オープンソースデータセットの学習と評価〜
第6回:物体検出のためのデータ収集
第7回:物体検出のためのアノテーション

今回の内容

・アノテーションとは

・アノテーションツール

・OpenCVによるアノテーション

・Windows「ペイント」

YOLOv8とは

YOLOv8は2023年1月に公開された最新バージョンであり、既存のオブジェクト検出器を上回り、速度と精度の面で限界を押し広げています。

物体検出だけでなく、セグメンテーションタスクや画像分類タスクでも利用することができます。

引用:https://github.com/ultralytics/ultralytics

YOLOv8のベンチマーク結果は以下となっています。

物体検出モデル

引用:https://github.com/ultralytics/ultralytics

セグメンテーションモデル

引用:https://github.com/ultralytics/ultralytics

なお、YOLOv8のライセンスは「GNU General Public License v3.0」となっています。

アノテーションとは

アノテーションとは、あるデータに対して関連する情報(メタデータ)を注釈として付与することを言います。

機械学習においては、モデルに学習させるための教師データ(正解データ、ラベル)を作成することを指します。

物体検出でのアノテーションとは、画像の中における物体の位置(座標)を明示することを言います。

具体的には、以下の画像を例に取ると、マスク着用を検出するための座標をテキストファイルとして保存する作業と言い換えることもできます。

sample.jpg

※各座標の考え方はこちらの記事で紹介しています。

0 0.5525 0.238274 0.1475 0.243902

# oject-class,	x_center,y_center,width,height

# ymin = y1/h,ymax = y2/h,xmin = x1/w,xmax = x2/w
# x_center = xmin + (xmax-xmin)/2
# y_center = ymin + (ymax-ymin)/2
# width = xmax-xmin
# height = ymax-ymin

YOLOv7では画像1枚に対して、1つのテキストファイル(例:教師画像「mask.jpg」に対して「mask.txt」)が必要となります。

1枚の画像の中に検出対象が複数ある時は、改行して同様に座標データを入力していきます。

画像に対して座標を入力して、テキストファイルを作っていく作業をアノテーションと言います。

以降では、このアノテーションの省力化のための方法を紹介していきます。

アノテーションツール

アノテーション作業を行う際には、フリーツールを使用することが一般的です。ここでは代表的なツールを紹介します。

vott2

Microsoft が公開しているアノテーションツールです。

こちらからダウンロードして使用してください。

Label me

LabelMeはMITよって開発された画像アノテーションツールです。

物体検出だけでセマンティックセグメンテ―ションやインスタンスセグメンテーションなどのアノテーションも行うことができます。

Anacondaで環境構築して、labelmeをインストールします。

pip install labelme

以下の通り実行すると、画面が立ち上がります。

labelme

まずは「Open」ボタンから画像を選択します。

画像が表示されました。

次に「Edit」から「Creat Rectangle」を選択します。

検出対象を枠線で囲います。

jsonファイルとして出力することができます。

OpenCVによるアノテーション

OpenCVからも画像の座標を取得することができます。

この方法は既存のアノテーションツールよりも自由度が高く、カスタマイズしたい方向けとなります。

ここではYOLOv7 で学習できる形式のアノテーションファイルを出力する方法を紹介します。

Anacondaで環境構築して、以下の通り実行します。

import cv2
import numpy as np

drawing = False
ix = -1
iy = -1

results = list()
def onMouse(event, x, y, flag, params):
    global drawing, ix, iy
    wname, img = params

    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        ix, iy = x, y
        
    if event == cv2.EVENT_MOUSEMOVE:
        img2 = np.copy(img)
        h,w = img2.shape[0], img2.shape[1]
        if drawing == False:
            cv2.line(img2, (x, 0), (x, h-1), (255, 0, 0))
            cv2.line(img2, (0, y), (w-1, y), (255, 0, 0))
        else:
            cv2.rectangle(img2,(ix,iy),(x,y),(0,0,255),1)
        cv2.imshow(wname, img2)

    if event == cv2.EVENT_LBUTTONUP:
        drawing = False
        cv2.rectangle(img,(ix,iy),(x,y),(0,0,255),1
        x_center = (ix+(x-ix)/2)/img.shape[1]
        y_center = (iy +(y-iy)/2)/img.shape[0]
        width = (x-ix)/img.shape[1]
        height = (y-iy)/img.shape[0]
        result = (str(label) + str(' ') + str(x_center)+str(' ')+str(y_center)+str(' ')+str(width)+str(' ')+str(height)+str(' ')+str('\n'))
        results.append(str(result))

入力画像を指定して実行すると画像が表示され、枠線で囲うことで座標を取得することができます。

以下の例ではラベルが単一である場合の例となります。

file_name = 'mask.jpg'

# ラベルの番号はここで変える
label = 0

img = cv2.imread(file_name)
wname='MouseEvent'
cv2.namedWindow(wname)
cv2.setMouseCallback(wname, onMouse, [wname, img])    
cv2.imshow(wname, img)
    
while True:
    
    cv2.imshow(wname, img)
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break
         
cv2.destroyAllWindows()

with open(os.path.basename(file_name).strip(".jpg")+'.txt', 'w') as f:
    f.writelines(results)  

実行すると以下のような画面が出ますので、対象物を枠線で囲っていきましょう。

「q」キーを押すと、画面が閉じられると同時にアノテーションファイルが出力されます。

YOLOv7 で学習できる形式のアノテーションファイルを作ることができました。

Windows「ペイント」

画像の座標を確認するということであれば、windowsのペイントなども使うことができます。

windowsPCでアプリケーションをインストールできないなどの制約があるケースでは有効かもしれません。

まずは対象物を長方形で囲います。

その後、左上にカーソルを合わせると、その座標が左下に表示されます。

この情報を元にアノテーションファイルを作成していきます。

左上の座標を(x1,y1)、右下の座標を(x2,y2)、画像サイズ(上の例だとW=800,H=533)として、以下のように換算します。

result = list()
label = 0

ymin = float(y1/H)
ymax = float(y2/H)
xmin = float(x1/W)
xmax = float(x2/W)

x_center = xmin + (xmax-xmin)/2
y_center = ymin + (ymax-ymin)/2
width = xmax-xmin
height = ymax-ymin

result.append(str(label)+str(' ')+str(x_center)+str(' ')+str(y_center)+str(' ')+str(width)+str(' ')+str(height)+str('\n'))

これを対象物の数だけ繰り返していきます。

全ての物体に対して座標の把握が終わったら、テキストファイルとして出力しましょう。

import os 
with open(os.path.basename(f).strip(".jpg")+'.txt', 'w') as f:
    f.writelines(result)  

YOLOv8 で学習できる形式のアノテーションファイルを作ることができました。

まとめ

最後までご覧いただきありがとうございました。

2023年1月に公開された物体検出でお馴染みのYOLOシリーズの最新バージョンである「YOLOv8」について、動かしながら試してみました。

精度・推論速度ともに向上しており、非常に使いやすいものになっています。

物体検出の活用の幅がさらに広がりそうですね。

コメントを残す