Dropbox

入門などと書いていますが、解説的なことは一切なく、やってみたら出来た手順の紹介です。

目的はここでは明かしませんが(出来るかどうか分かっていないw)、サンプル画像などから自ずと分かってくることでしょう。

世の中にない目的物を認識するためには自分で学習させないといけません。それを教師付き学習という手法で行います。その手順を示すことが、この記事の主な目的です。

[ Python3で仮想環境を作る ]
とりあえずコマンドラインでpython3が起動することを確認してください。記憶は定かではありませんがMacOS Sonomaでも何かしら作業を行わないと動かないかも知れません。その辺りはググっていただきたいです。WindowsならばPython3の導入が必要ですが、ここでは詳細は省きます。また以下の手順はMacOSを使用しています。

後から簡単に無かったことに出来るのでpythonの仮想環境を作って試すことをお勧めします。ターミナルを開き作業用のディレクトリーにて以下の呪文を唱えれば良いです。

python3 -m venv .yolo
source ./.yolo/bin/activate

.yoloは任意の名前です。最初のピリオドは無くても良いです。

以下の作業は全てこの仮想環境で行なっています。

[ アノテーション ]
学習する元データとなるサンプル画像をなるべく多数用意します。そして一枚一枚の画像の中で目標物の範囲を指定し、それが何者であるかのラベルを付けていく作業です。根気と忍耐が試されるステージとなります。

使用するツールはいくつか存在しますが、最初に試したのはlabelImgというものでした。「YOLOv8自作データセットの学習方法(ローカルでも動かすよ)」という記事が詳しいです。手軽に試すには良いのですが、作業を中断したり、後から画像を追加したりするのが難しいので軽いテストで使用するに留まりました。

現在はLabel Studioというツールを使用しています。作業用のPCに入れてローカルでも使えますが、元々サーバーに入れて使うことを前提に考えられているものなので作業用PCとは別のUbuntuサーバーで動かしています。複数の作業者で一つのプロジェクトを完成させるような作りですので作業を途中で中断したり、データを追加するのも自由自在です。Label Studioの使用方法については「多機能アノテーションツールLabelStudioの使い方を解説」という記事が詳しいです。

とりあえず手順の確認のため50枚強の画像を準備しました。元データはFPVドローンのゴーグルで録画した動画ファイルです。動画に直接アノテーションを行う手法もあるようですが、まずは静止画で行います。動画ファイルから使えそうな画像を切り出した静止画(jpgファイル)をLabel Studioにアップロードし、一枚一枚にラベルを付けていきます。これくらいの枚数ならば大して時間はかかりません。

出来上がったらYOLO形式でExportして作業用のPCにダウンロードします。zipファイルになっているので適当なところに解凍して分かりやすいフォルダー名に変更しておきます。

[ YOLOv8 ]
いよいよ学習モデルの作成です。色々な事例を真似してみましたがUltralyticsのYOLOv8パッケージを使用する方法が簡単で確実です。ドキュメントもよく出来ています。これを利用した事例の紹介も多数ありますがサンプルコードは公式ドキュメントと同じものがほとんどです。このブログ記事も含めて、事例紹介を読むより公式ドキュメントをじっくり読むことをお勧めします。

良くわっていませんが、プログラムとしてはYOLOv8ですが学習の元となるモデルはYOLOv10まで進んでいるようです。自分の目的を達成するために、どのモデルを使い、どれくらい学習させれば良いかは試してみるしかないようです。何はともあれ動かしてみます。

[ M2 MacBook Airでの学習 ]
ultralyticsを導入します。

pip install ultralytics

で、いよいよ学習するためのスクリプトです。

import time
from ultralytics import YOLO

start = time.time()
print(f'start time: {start}')
model = YOLO('yolov9s.pt')
model.info()
model.train(data='fpv.yaml', epochs=10, imgsz=640, device='mps')
trained = time.time()
print(f'elpased time: {trained-start}')
model.val()
end = time.time()
print(f'end time: {end - start}')

yolov9s.ptというのが元になるモデルで、何かしらのラベルが付いた学習済みモデルになっています。ここにyolov9s.yamlというファイルを指定して学習させると、全くのゼロからの学習になるらしいですが、ptファイルを使った方が速く結果が出るように思えます。yolov9s.ptは比較的軽いモデルです。目的や学習環境に合わせて、ここを変えます。モデル毎の特徴についてはYOLOのドキュメントを見てください。YOLOv9YOLOv10のリンクを貼っておきます。

epochs=10というのは学習を繰り返す回数です。お試しなので少なめにしておきます。device=’mps’はAppleのM2チップのGPUを使用するためのおまじないです。device=を省略するとMacBookの場合はCPUによる稼働になります。NVIDIAのGPUが実装されている環境ではdeviceの指定がなくても自動的にGPUを使用します。

fpv.yamlというファイルでラベルを付けたデータの置き場所を指定します。内容は以下の通りです。

# fpvgoals dataset

# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/]
train: /Users/kozak/Downloads/fpvgates
val: /Users/kozak/Downloads/fpvgates

# number of classes
nc: 2

# class names
names: ['gate','goalgate']

trainとvalの所で指定しているのはLabel StudioからExportしたYOLO形式のzipファイルを展開したフォルダーです。ncは作成したラベルの数に合わせます。namesにはラベル名を書いておきます。

これで先のスクリプトを走らせれば自前の学習済みデータが出来上がります。結果は’runs/detect/train{n}/’ ({n}は数字と置き換えて読んでください)以下に入ります。学習結果を示す各種データがありますが、あまり良くは研究していないです。result.pngを見比べるとepochによる繰り返しが適当な回数になったかどうかが分かるような気もします。出来上がったモデルはweights/bets.ptです。これを使って画像認識を行います。

[ 動画に画像認識をかける ]
いきなりスクリプトを提示します。

import cv2
import time
from ultralytics import YOLO
model = YOLO("./runs/detect/train13/weights/best.pt")
model.to('mps')

video_path = "../video/test2.mov"
cap = cv2.VideoCapture(video_path)
t1 = time.time()
while cap.isOpened():
  success, frame = cap.read()
  if success:
    results = model.track(frame, persist=True)
    annotated_frame = results[0].plot()
    cv2.imshow("FPV Tracking", annotated_frame)
    t2 = time.time()
    print("elapsed: " + str(t2-t1))
    t1 = t2
    if cv2.waitKey(1) & 0xFF == ord("q"):
      break
  else:
    break
cap.release()
cv2.destroyAllWindows()

最初の方にあるbest.ptが自分で生成したモデルです。その直後にある’model.to(‘mps’)はApple M2チップのGPUを使用するためのおまじないです。
“../video/test2.mov”で用意した動画に対して画像認識を行います。単純なトラッキングならば動画を直接YOLOに渡してしまっても良いのですが、画像認識の結果(resultsに格納される各種データ)を後からプログラムで処理するためにOpenCV2にて画像をフレームごとに分解して解析を行うようにしています。

下の例は、もうちょっと深く学習させてからの例ですが、様子的には同じものが出てくきます。

少しテストしてみるとepochs=10では足りなくて200回か300回回した方が良いと分かります。問題は処理時間でM2 MacBook Airでは一晩走らせても終わらないということもあります。あと16GBメモリーのMBAでもメモリーが足りなくなりそうでした。

ということで、探求は次回に続きます。

Trackback

no comment untill now

Add your comment now