やること
こんにちは、Suzuです。
皆さん、洗濯機の蛇口はちゃんと毎回閉めていますか?開けっぱなしだと劣化が早まるのだそうです。また、万が一ホースが抜けたときに水浸しになるリスクもあります。
あれ、玄関の鍵閉めたっけ? (°□°; )
あれ、洗濯機の蛇口閉めたっけ? ( °□° )
外出時の不安の種トップ2です。
以前、洗濯槽内のティッシュを検出するシリーズを公開しました。
これを発展させて、洗濯機の蛇口の閉め忘れを防止するため、蛇口の開閉状態を監視してLINE通知するシステムを作りました。(洗濯機好きすぎない?)
水栓の開閉状態はカメラ+画像処理で検出します。検出結果はLINE Notifyというサービスを利用して通知します。前回は「ティッシュ」という1クラスの検出だったのに対し、今回は「閉」「開」という2クラスの検出になっています。
参考文献
データセットの準備、学習、検出までは前回のティッシュシリーズを踏襲します。細かい手順はそちらを参照してください。
今回もYOLOv8を使用しました。
YOLOv8の出力形式についてはこちらのサイトを参考にさせていただきました。
水栓画像の収集
Macの内蔵カメラで水栓が「開いている」「閉まっている」写真を合計146枚撮りました。写真は学習用データ(train)と検証用データ(val)に振り分けます。trainとvalの比率は7:3または8:2がおすすめです。
取っ手が右側に来ているのが閉まっている状態。trainデータ51枚、valデータ22枚になりました。
取っ手が下側に来ているのが開いている状態。同じくtrainデータ51枚、valデータ22枚になりました。
フォルダ構造は次のとおりです。ファイル名はただの連番で、順番を気にする必要はありません。
アノテーション
今回もアノテーションツール「labelImg」を使ってアノテーションしました。水栓をバウンディングボックスで囲んで、閉=0、開=1のラベリングを行います。PascalVOCを「YOLO」に変えることを忘れないでください。
このようなテキストファイルが生成されます。クラス番号、バウンディングボックスの中心X座標、中心Y座標、幅、高さ(の比率)です。今回、クラス番号は0と1があります。
0 0.518403 0.653646 0.206250 0.315625
アノテーションデータは赤字の部分に配置しました。クラス番号はtxtファイルの中に記述されているので、ファイル名の数字とは関係がありません。
データセットの完成
「datasets」フォルダを丸ごとzipに圧縮します。データセットのパス、クラス数、クラス名を指定するファイル「dataset.yaml」ファイルを作成します。後ほどColab上にアップして学習するためパスは「/content」から始めます。
ティッシュの記事と異なる点として、検出したい物体が二つ存在します。なのでncを2、namesを [’water_close’, ’water_open’] と設定します。
# Path
path: /content/datasets/suzu # dataset root dir
train: /content/datasets/suzu/images/train # train images (relative to 'path')
val: /content/datasets/suzu/images/val # val images (relative to 'path')
# Classes
nc: 2 # number of classes
names: ['water_close','water_open'] # class names
zipとdataset.yamlをColab上のディレクトリにアップロードしたら準備完了です。
学習
Colabにアップしたデータセットを展開します。
!unzip datasets.zip
YOLOv8はPythonライブラリ「ultralytics」に入っているのでインストールします。Pytorchも必要ですがColabにプリインされています。
!pip install ultralytics
ティッシュのときと同じですね。これで学習します。
from ultralytics import YOLO
#モデル指定
model = YOLO('yolov8n.pt')
#データセットを学習
results = model.train(data='dataset.yaml', epochs=100)
・
・
・
100 epochs completed in 3.096 hours.
Optimizer stripped from runs/detect/train2/weights/last.pt, 6.2MB
Optimizer stripped from runs/detect/train2/weights/best.pt, 6.2MB
Validating runs/detect/train2/weights/best.pt...
Ultralytics YOLOv8.2.18 🚀 Python-3.10.12 torch-2.2.1+cu121 CPU (Intel Xeon 2.20GHz)
Model summary (fused): 168 layers, 3006038 parameters, 0 gradients, 8.1 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 2/2 [00:09<00:00, 4.90s/it]
all 44 44 0.992 0.973 0.994 0.558
water_close 44 23 1 0.994 0.995 0.536
water_open 44 21 0.984 0.952 0.993 0.58
Speed: 2.1ms preprocess, 184.3ms inference, 0.0ms loss, 1.0ms postprocess per image
Results saved to runs/detect/train2
runs/detect/train2/weights/last.pt
runs/detect/train2/weights/best.pt
に学習済みモデルが自動保存されています。「last.pt」は最後のモデル、「best.pt」は学習中にもっとも精度が高かったモデルです。
すでに「best.pt」で検証(バリデーション)も行ってくれています。学習に使用していない「閉」22枚、「開」22枚を判定した結果、だいたい1ミスくらいの精度であることが分かります。興味があれば「P」「R」「mAP50」「mAP50-95」がどんな指標か調べてみてください。
さいごに
これで学習済みモデルができました!次回、LINE通知まで実装して監視を行ってみましょう!