見出し画像

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が厳しい条件でも適度な性能を示しています。

良いかどうかの判断基準

  1. 用途に応じた閾値

    • 例えば、安全や品質管理など、誤検出(False Positive)を減らしたい場合は、Precisionが重要です。

    • 一方で、検出漏れ(False Negative)を減らしたい場合は、Recallを重視します。

  2. クラスごとのバランス

    • anormalの方がnormalより性能が良いです。このバランスが重要な場合、normalの改善が必要です。

  3. 用途における基準

    • 実務では、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で一回しできることを確認したので、モデルを増やしてより精度を上げてみたいと思っています。

いいなと思ったら応援しよう!