OpenCVでYOLOの学習用画像を撮影するツールを作る|Pythonで学習データを効率よく集める

YOLO

YOLOモデルを学習させるために、最初に必要になるのが学習用画像です。

AIの認識率は学習データの質に大きく左右されるため、まずはできるだけ多くの画像を集める必要があります。

最初はスマートフォンで撮影することも考えましたが、PCへ転送したりファイルを整理したりと、思った以上に手間がかかりました。

そこで今回は、OpenCVを使って学習用画像を簡単に撮影・保存できるツールを作成しました。

この記事では、

  • なぜ撮影ツールを作ったのか
  • カメラ設定
  • 保存機能
  • 実際の撮影方法

について紹介します。


この記事で完成するもの

今回作成するツールでは、次のことができます。

  • USBカメラの映像をリアルタイムで表示
  • 解像度・フォーカス・露出を固定
  • Sキーを押すだけで画像を保存
  • ESCキーで終了

学習用画像を効率よく集めることだけに特化した、シンプルな撮影ツールです。


なぜ撮影ツールを作ったのか

YOLOのモデルは、一度学習したら終わりではありません。

認識率を改善するためには、

  • 新しい画像を追加する
  • 学習し直す

という作業を何度も繰り返します。

つまり、

学習用画像を追加する作業は何度も発生します。

そのたびに、

  • スマートフォンで撮影
  • PCへ転送
  • フォルダへ保存

という作業を行っていては、改善するたびに時間がかかってしまいます。

そこで、

「思いついたらすぐ撮影できる環境」

を作るために、専用の撮影ツールを作成しました。

必要な機能は、

ライブ映像を表示して、キーを押したら保存する。

それだけです。

機能を増やしすぎず、撮影に特化したシンプルなツールにしました。


OpenCVをインストール

まずはOpenCVをインストールします。

PythonからOpenCVを利用するには、次のコマンドを実行します。

pip install opencv-python

インストールが完了したら、次のコードで正しくインポートできるか確認してみましょう。

import cv2

print(cv2.__version__)

エラーが表示されず、バージョン番号が表示されれば準備完了です。

今回作成する撮影ツールでは、OpenCVを使って

  • USBカメラの映像を取得する
  • 画面へリアルタイム表示する
  • 画像を保存する

という3つの処理を行います。

それでは実際にカメラ映像を取得していきます。


OpenCVでカメラ映像を取得する

まずはOpenCVでUSBカメラを開きます。

cap = cv2.VideoCapture(0)

これだけでカメラ映像を取得できます。

取得した映像はリアルタイムで画面へ表示し、

学習に使いたいタイミングで保存できるようにしています。


カメラ設定を固定する

AIの学習では、

できるだけ毎回同じ条件で撮影することが重要です。

私が使用しているWebカメラは、オートフォーカスや自動露出の精度があまり高くなく、撮影するたびにピントや明るさが変化してしまいました。

そのままでは同じ牌を撮影していても画像の見え方が変わってしまい、学習データに不要なばらつきが生まれてしまいます。

そこで今回は、撮影条件をできるだけ一定にするため、次の3つを固定しています。

  • 解像度
  • フォーカス
  • 露出

を固定しています。


解像度

cap.set(cv2.CAP_PROP_FRAME_WIDTH, 2560)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1440)

今回は2560×1440で撮影しています。

解像度を固定することで、

あとから画像を加工するときも扱いやすくなります。


オートフォーカスをOFFにする

cap.set(cv2.CAP_PROP_AUTOFOCUS, 0)
cap.set(cv2.CAP_PROP_FOCUS, 100)

オートフォーカスを有効にしていると、

撮影するたびにピント位置が変わってしまいます。

すると、

同じ牌を撮影していても見え方が少しずつ変わり、

学習データの品質が安定しません。

そこで、

今回はフォーカスを固定して撮影しています。


露出も固定する

cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1)
cap.set(cv2.CAP_PROP_EXPOSURE, -6)

露出もオートのままでは、

部屋の明るさによって画像が毎回変わってしまいます。

そのため露出も固定しました。

もちろん、

後から紹介するデータ拡張では明るさをランダムに変化させていますが、

元になる画像は安定した品質で撮影する

という考えで作っています。


Sキーを押すだけで保存する

学習データは何千、何万枚の画像が必要になってきます。

そのため、

保存操作はできるだけ簡単にしました。

今回は、

Sキーを押すだけで画像を保存できます。

elif key == ord("s"):

保存するファイル名には現在時刻を使用しています。

そのため、

ファイル名が重複することもなく、

撮影した順番も分かりやすくなっています。


実際の撮影方法

撮影するときは、

麻雀卓へ牌を並べ、

少しずつ位置や向きを変えながら撮影しています。

例えば、

  • 手牌を左右へずらす
  • 少し角度を変える
  • 並び順を変える
  • 牌を置き直す

など、

毎回少しだけ変化を付けています。

この段階では、

大量に撮ることよりも、

さまざまな配置の画像を集めること

を意識しました。

あとから紹介する学習データ生成ツールやデータ拡張を組み合わせることで、

さらに大量の学習データを作成できるようになります。


ソースコード全文

以下が、今回紹介した撮影ツールのコードです。

import os
import cv2
from datetime import datetime

# 保存先フォルダ
SAVE_DIR = "./sample"
os.makedirs(SAVE_DIR, exist_ok=True)

cap = cv2.VideoCapture(0)

cap.set(cv2.CAP_PROP_FRAME_WIDTH, 2560)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1440)
cap.set(cv2.CAP_PROP_AUTOFOCUS, 0)
cap.set(cv2.CAP_PROP_FOCUS, 100)
cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1)
cap.set(cv2.CAP_PROP_EXPOSURE, -6)

if not cap.isOpened():
    print("カメラが開けません")
    exit()

frame = None

while True:
    ret, frame = cap.read()
    if not ret:
        continue

    display = frame.copy()

    cv2.putText(display, "LIVE", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)

    cv2.imshow("操作:{s:保存, ESC:終了}", display)

    key = cv2.waitKey(1) & 0xFF

    # ESCで終了
    if key == 27:
        break
    
    # 保存
    elif key == ord('s'):
        if frame is not None:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filepath = os.path.join(SAVE_DIR, f"{timestamp}.jpg")

            cv2.imwrite(filepath, frame)
            print(f"保存: {filepath}")

cap.release()
cv2.destroyAllWindows()

まとめ

今回は、

YOLOの学習用画像を撮影するためのツールを紹介しました。

ツール自体は非常にシンプルですが、

  • 解像度を固定する
  • フォーカスを固定する
  • 露出を固定する
  • ワンキーで保存できるようにする

といった工夫を入れることで、

学習データを効率よく集められるようになりました。

次回は、

撮影した画像に矩形を付けるアノテーションツールについて紹介します。


関連記事

コメント

タイトルとURLをコピーしました