MD-TESEにおける対象物の自動検出をやってみる(Yolo8)
はじめに
先日Yolo8を動かせる環境が整ったことを確認できましたので、何か具体例を挙げてやってみたいと思います。
不妊治療を題材に
以前、男性不妊治療のプロセスの一つで顕微鏡で対象物を探すという話を耳にしたことがあります。これを自動化して顕微鏡を使って探すことができたら仕事の効率化を向上できるのではと聞きました。そこで、すでにモデル構築の際に必要な画像をRoboflowを使って学習させてから、動画をshutterstockで用意して推論させてみたいと思います。まず利用できる素材を使ってどこまでできるのか確認してみました。
Roboflowから学習する画像を取得する
このページ(sperm-stage2 Computer Vision Project)からダウンロードします。
Yolov8を選択、Download zip to computerを選択してContinueします。
zipを伸長して以下を予め作成したprojectフォルダの下に配置する。私の場合は、H:\Family_data\Michi\python\yolo311\project2
data.yamlファイルを書き換える
上3行を絶対パスで書きます。(それが安全)
train: H:\Family_data\Michi\python\yolo311\project2/train/images
val: H:\Family_data\Michi\python\yolo311\project2/valid/images
test: H:\Family_data\Michi\python\yolo311\project2/test/images
nc: 2
names: ['anormal', 'normal']
roboflow:
workspace: ghamgui-amine-pizjw
project: sperm-stage2
version: 1
license: CC BY 4.0
url: https://universe.roboflow.com/ghamgui-amine-pizjw/sperm-stage2/dataset/1
学習を行う
まず仮想環境を起動する
cd H:\Family_data\Michi\python\yolo311
.\Scripts\activate
次に学習させる
cd project2
yolo task=detect mode=train model=yolov8n.pt data=data.yaml epochs=100 imgsz=640
以下のような画面が出る(Epoch1~)
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
1/100 0G 2.241 3.755 1.752 184 640: 100%|██████████| 10/10 [00:27<00:00, 2.
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 1/1 [00:01<0
all 15 97 0.0138 0.583 0.0221 0.00612
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
2/100 0G 2.018 2.589 1.433 146 640: 100%|██████████| 10/10 [00:24<00:00, 2.
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 1/1 [00:00<0
all 15 97 0.0175 0.807 0.0882 0.0348
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
99/100 0G 0.7588 0.524 0.9205 91 640: 100%|██████████| 10/10 [00:23<00:00, 2.
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 1/1 [00:00<0
all 15 97 0.844 0.765 0.841 0.508
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
100/100 0G 0.7156 0.4903 0.8978 129 640: 100%|██████████| 10/10 [00:23<00:00, 2.
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 1/1 [00:00<0
all 15 97 0.856 0.741 0.844 0.514
100 epochs completed in 0.703 hours.
Optimizer stripped from runs\detect\train3\weights\last.pt, 6.3MB
Optimizer stripped from runs\detect\train3\weights\best.pt, 6.3MB
Validating runs\detect\train3\weights\best.pt...
Ultralytics 8.3.36 🚀 Python-3.11.3 torch-2.5.1+cpu CPU (12th Gen Intel Core(TM) i5-12400)
Model summary (fused): 168 layers, 3,006,038 parameters, 0 gradients, 8.1 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 1/1 [00:00<0
all 15 97 0.79 0.817 0.877 0.527
anormal 12 63 0.901 0.825 0.925 0.548
normal 13 34 0.679 0.809 0.83 0.507
Speed: 1.3ms preprocess, 40.1ms inference, 0.0ms loss, 0.5ms postprocess per image
Results saved to runs\detect\train3
💡 Learn more at https://docs.ultralytics.com/modes/train
学習評価について
Box(P): Precision(適合率)
予測が正解である確率。高いほど、誤検出が少ないことを示します。
全体で0.79、クラス別では特にanormalで0.901と高いです。
誤検出を抑えたい場合、これは良い値です。
R: Recall(再現率)
実際に存在する正解をどれだけ検出できたか。高いほど検出漏れが少ないことを示します。
全体で0.817、クラス別ではanormalとnormalでそれぞれ0.825と0.809。
検出漏れを抑えたい場合、これも悪くありません。
mAP@50: 平均適合率(IoU閾値50%)
モデルの全体的なパフォーマンスを示す指標で、0.877は良好な値です。
anormalは0.925で非常に高く、normalも0.83で十分な値と言えます。
mAP@50-95: mAPをより厳しいIoU閾値で評価したもの(厳密な精度の指標)
全体で0.527。anormalが0.548、normalが0.507。IoUが厳しい条件でも適度な性能を示しています。
良いかどうかの判断基準
用途に応じた閾値
例えば、安全や品質管理など、誤検出(False Positive)を減らしたい場合は、Precisionが重要です。
一方で、検出漏れ(False Negative)を減らしたい場合は、Recallを重視します。
クラスごとのバランス
anormalの方がnormalより性能が良いです。このバランスが重要な場合、normalの改善が必要です。
用途における基準
実務では、mAP@50で0.8以上であれば、一般的に良い性能とされます。この結果では0.877なので、良いと評価できます。
改善の余地
normalクラスのRecall向上
検出漏れを減らすために、normalのRecall(0.809)をさらに高めることを検討。
例えば、データの増強やクラス間のバランスを改善することが有効です。
mAP@50-95の向上
厳しいIoU条件下での性能向上が必要なら、より高精度なモデルやハイパーパラメータチューニングを行う。
学習結果の結論
この結果は、一般的な基準では「良い」と言えます。ただし、用途に応じてクラスバランスやRecallの向上を検討することで、より適切なモデルに近づけることができます。
推論を行う
動画を使って推論をしてみます。動画はこのページからダウンロードしました。ダウンロードしたファイルは、suironフォルダを作りそこに配置しました。ファイル名はsuiron3.webmとしました。
H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm
以下のコマンドで推論を実行します。
yolo task=detect mode=predict model=runs/detect/train3/weights/best.pt source=H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm --conf=0.2
実行後以下の画面が走ります。(フレームごとの検出数等が表示されます)
Ultralytics 8.3.36 🚀 Python-3.11.3 torch-2.5.1+cpu CPU (12th Gen Intel Core(TM) i5-12400)
Model summary (fused): 168 layers, 3,006,038 parameters, 0 gradients, 8.1 GFLOPs
video 1/1 (frame 1/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 7 anormals, 1 normal, 47.3ms
video 1/1 (frame 2/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 7 anormals, 1 normal, 15.5ms
video 1/1 (frame 3/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 6 anormals, 2 normals, 15.6ms
video 1/1 (frame 4/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 6 anormals, 1 normal, 31.2ms
video 1/1 (frame 5/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 7 anormals, 25.2ms
video 1/1 (frame 6/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 5 anormals, 1 normal, 31.2ms
video 1/1 (frame 7/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 4 anormals, 1 normal, 15.6ms
video 1/1 (frame 8/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 3 anormals, 2 normals, 16.7ms
video 1/1 (frame 9/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 4 anormals, 2 normals, 15.6ms
video 1/1 (frame 10/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 5 anormals, 1 normal, 15.6ms
video 1/1 (frame 446/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 5 anormals, 16.0ms
video 1/1 (frame 447/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 8 anormals, 31.3ms
video 1/1 (frame 448/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 7 anormals, 15.6ms
video 1/1 (frame 449/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 6 anormals, 31.7ms
video 1/1 (frame 450/450) H:\Family_data\Michi\python\yolo311\project2\suiron\suiron3.webm: 384x640 4 anormals, 2 normals, 16.3ms
Speed: 1.6ms preprocess, 25.2ms inference, 0.6ms postprocess per image at shape (1, 3, 384, 640)
Results saved to runs\detect\predict4
💡 Learn more at https://docs.ultralytics.com/modes/predict
検出結果を確認する
H:\Family_data\Michi\python\yolo311\project2\runs\detect\predictにsuiron3.aviのファイルが生成されます。(動画を貼り付けられないのでスクリーンショットをいかに貼ります)
思ったより検出できています。驚きました。
推論済の動画ファイルを以下に添付します。
おわりに
ひとまず自分のPCで一回しできることを確認したので、モデルを増やしてより精度を上げてみたいと思っています。