google driveのディレクトリ構成
マイドライブに「data」フォルダを作成しておく
content
|_____drive
|_____My Drive
|_____data
作業ディレクトリの作成
PCで画像の収集やアノテーションを行うため、作業ディレクトリを作成しておく
python_yolov5
|__________images
| |__________colab_upload
| | |__________test
| | |__________train
| | |__________val
| |
| |__________resource
|
|__________1_get_img.py
|__________2_rename.py
|__________3_DataAugumentation.py
|__________4_shuffle.py
学習したい物体が映った画像を収集
1_get_img.pyの中身
from icrawler.builtin import GoogleImageCrawler
crawler = GoogleImageCrawler(storage={"root_dir": "resourceフォルダのパス"})
#keyword => 入手したい画像のキーワード
#max_num => 入手する画像の枚数
crawler.crawl(keyword='腕時計', max_num=100)
print('-----finifh-----')
resourceフォルダの中に画像が保存されているはずです。
自前の画像データがある場合は1_get_img.pyを実行せずにresourceフォルダに格納するだけで良いです。
画像のリネーム
2_rename.pyの中身
import os
import glob
path = "resourceフォルダのパス"
files = glob.glob(path + '/*')
#画像の名前を番号に変更し.pngで保存する
for i, f in enumerate(files, 1):
os.rename(f, os.path.join(path, '{0:05d}'.format(i) + '.png'))
#print(i)
画像を扱いやすくするために名前を番号に、拡張子をpngに変更しています。
学習に用いるデータは数が多いのでpythonで実行した方が良いです。
データの拡張
3_DataAugumentation.pyの中身
import cv2
import pathlib
input_dir = "resourceフォルダのパス"
output_dir = "resourceフォルダのパス"
image_list_png = list(pathlib.Path(input_dir).glob('**/*.png'))
rot_angle=180
for i in range(len(image_list_png)):
img_png = cv2.imread(str(image_list_png[i]), cv2.IMREAD_COLOR)
h,w=img_png.shape[:2]
ROT= cv2.getRotationMatrix2D(center=(w/2,h/2),angle=rot_angle,scale=1)
img_png = cv2.warpAffine(img_png,ROT,dsize=(w,h))
output_path = output_dir + '/' + 'add_ud_' + image_list_png[i].name
cv2.imwrite(output_path, img_png)
#print('ud_' + str(i))
for i in range(len(image_list_png)):
img_png_flip = cv2.imread(str(image_list_png[i]), cv2.IMREAD_COLOR)
img_flip_lr = cv2.flip(img_png_flip, 1)
output_path = output_dir + '/' + 'add_fp_' + image_list_png[i].name
cv2.imwrite(output_path, img_flip_lr)
#print('fp_' + str(i))
print('----------finish----------')
より正確に物体の推論を行うためにはより多くのサンプルが必要になります。
しかし、大量のサンプルデータを収集するのは非常に大変な作業のため、用意した画像を上下反転、左右反転してデータを3倍に増やします。
3_DataAugumentation.py実行後、resourceフォルダの中身が増えているはずです。
アノテーションを行う
アノテーションツールを使用してアノテーションを行います。
今回は「labelImg」を使用します。
コマンドプロンプトにてインストールします。
pip3 install labelImg
インストールできたらコマンドプロンプトから実行します。
labelImg
「labelImg」を用いたアノテーションのやり方については省略します。
画像データが格納されているresourceファイルに各画像と同じ名前で保存していきます。
出力形式をYOLOに変更するのを忘れないでください。
アノテーション後のresourceフォルダの中身
resource
|__________00001.png
|__________00001.txt
|__________00002.png
|__________00002.txt
|
画像の振り分け
これまでに用意した画像をtrain, test, valに分けて別々のフォルダに移動させていきます。
今回はtrain:test:val=7:1:2という比率で分けていきます。
4_shuffle.pyの中身
import glob
import os
import random
import shutil
import numpy as np
input_dir = "resourceフォルダのパス"
save_dir = "colab_uploadフォルダのパス"
def split_data(folder,savefolder,train_rate,val_rate):
imgs = glob.glob(os.path.join(folder,"*.png"))
txts = glob.glob(os.path.join(folder,"*.txt"))
imgs_index = np.array(range(len(imgs)))
imgs_index_shuffle = np.random.permutation(imgs_index)
n = len(imgs)
train_n = int(n * train_rate)
val_n = int(n * val_rate)
test_n = n - train_n - val_n
print(train_n,test_n,val_n)
for i, index in enumerate(imgs_index_shuffle):
img_path = imgs[index]
txt_path = txts[index]
img_name = img_path.split("\\")[10]
txt_name = txt_path.split("\\")[10]
print(img_name,txt_name)
if i < train_n:
shutil.copyfile(img_path, savefolder + f"/train/{img_name}")
shutil.copyfile(txt_path, savefolder + f"/train/{txt_name}")
elif train_n <= i < train_n + val_n:
shutil.copyfile(img_path, savefolder + f"/val/{img_name}")
shutil.copyfile(txt_path, savefolder + f"/val/{txt_name}")
else:
shutil.copyfile(img_path, savefolder + f"/test/{img_name}")
shutil.copyfile(txt_path, savefolder + f"/test/{txt_name}")
#振り分けの比率(train:test:val=7:1:2)
split_data(input_dir,save_dir,0.7,0.1)
4_shuffle.pyを実行するとresourceフォルダ内のデータがランダムでcolab_uploadフォルダ内のtrain,test,valフォルダに振り分けられます。
この振り分けられたtrain,test,valフォルダをそのままgoogledriveのdataフォルダ内にuploadします。
「yolo.yaml」の作成
中身
#train,test,valのパスを指定
train: /content/drive/My Drive/data/train
val: /content/drive/My Drive/data/val
test: /content/drive/My Drive/data/test
#検出するクラスの数
nc: 1
#検出する各クラスの名前 "name1", "name2"・・・
names: ["clock"]
「yolo.yaml」をdataフォルダ内にuploadする
My Drive
|_____data
|_____train
|_____val
|_____test
|_____yolo.yaml
colabでの操作
My Drive直下にgoogle colabのipynbファイルを作成する
ランタイムのタイプを「T4 GPU」に変更
以下をgooglecolabで実行
#ドライブのマウント
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/MyDrive/data
#必要なライブラリのインストール
!pip3 install ultralytics
学習開始
続いてcolabで以下を実行
!yolo task=detect mode=train model=yolov8n.pt data=yolo.yaml epochs=50 imgsz=640 batch=16
「model=」では次のうちどれかを指定します。
求める精度・速度や環境に応じて選択します。
今回は一般的なノートPCで推論するため、速度が速く軽い「YOLOv8n」を選択しています。
詳しくはultralyticsのドキュメントを見てください。
https://docs.ultralytics.com/ja/tasks/detect/
- YOLOv8n
- YOLOv8s
- YOLOv8m
- YOLOv8l
- YOLOv8x
学習が終わるまで待機します
物体検出をやってみる
google driveのマイドライブある「data」フォルダ内に「runs」というフォルダが作成されています。
「/runs/detect/train/weights/best.pt」これをPCにダウンロードしてください。
コマンドプロンプトにて以下を実行
pip3 install ultralytics
Pythonで次のコードを実行(WEBカメラによるリアルタイム推論)
from ultralytics import YOLO
model = YOLO("ダウンロードしたbest.ptのパス")
#conf信頼度(conf=0.5 => 信頼度50%以上のオブジェクトを表示)
results = model(0 , show=True, conf=0.5)
for i in enumerate(results):
print(i)
実際のリアルタイム推論の様子(スクショ)
高い信頼度で時計として認識出来ていますね。
しかし、時計と似ているものにも反応してしまいました。
(タイマー付き電源タップ)これに関しては似すぎていると思うが...
また、取得してきた時計の画像が丸いものに偏っていたせいか、信頼度は低いものの、丸いものにも反応しています。
このような問題を回避するためには
- 学習データの増量
- 学習回数の増加
- confの値を大きくする
などを行い試行錯誤する必要があります。
0 件のコメント:
コメントを投稿