BLOG

シンラボメンバーのあれこれ

  1. HOME
  2. ブログ
  3. 技術記事
  4. OpenCV+pythonで機械学習をやってみた③_実践編

OpenCV+pythonで機械学習をやってみた③_実践編

※本記事は、「OpenCVによるAIの実装方法」「機械学習まであと1歩!写真から顔や物体を取り出すには? 実装編第2回」「OpenCVで機械学習をさせてみた!! 実装編第3回」を再編集したものです。

みなさんこんにちは。沖田はじめです。
今回は、OpenCVで教師あり学習を行うに当たって、前回お話した基礎知識を元に自動車の検出を実践したいと思います。(※前回の基礎知識編の記事はこちら

◆開発環境構築
それでは、開発に必要な環境を構築していきましょう。
まず、以下のツールをダウンロードします。

Miniconda3
Windows10 64bit環境の場合は、「Python 3.9 Miniconda3 Windows 64-bit」をダウンロードします。

OpenCV3.4.14
最新のOpenCV(※2021年6月現在 4.5.2)はMiniconda3からインストールしますが、opencv_createsamplesとopencv_traincascadeは、OpenCV4以上には含まれなくなりましたので、公式サイトから別途ダウンロードする必要があります。

IrfanView
正解画像の中から対象物の位置と矩形の大きさを取得できます。同様の事ができれば、他ツールを使っても構いません。Windows10 64bit環境の場合は、IrfanView(64bit版)をダウンロードします。

次に、ダウンロードしたツールのセットアップをします。

・Miniconda3のセットアップ
インストーラを開いてインストールしてください。特にインストール先を指定しない場合、C:\ユーザー\ユーザー名\miniconda3 にインストールされます。

・OpenCV4.5.2のインストール
WindowsのスタートメニューのAnaconda3から、Anaconda Prompt を起動します。
Anaconda Prompt上で pip install opencv-python と入力すると、インストールされます。

・Miniconda3にopencv_createsamplesとopencv_traincascadeをコピーする
ダウンロードしたopencv_3.4.14から、opencv_createsamplesとopencv_traincascadeをMiniconda3にコピーします。

まず、ダウンロードしたOpenCV 3.4.14(opencv-3.4.14-vc14_vc15.exe)を実行します。すると、opencvフォルダができあがります。

次に、Anaconda Promptを起動し、Prompt上で where python と入力し、miniconda3内でのpythonのインストール先ディレクトリを確認します。

  (base) E:\MyData\Miniconda3>where python
  C:\ユーザー\ユーザー名\miniconda3\python.exe

 そして、pythonインストール先にある Library\bin に、OpenCV 3.4.14の build\x64\vc14\bin にある、下記のファイルをコピーします。

   opencv_createsamples.exe
   opencv_traincascade.exe
   opencv_world3414.dll
   opencv_world3414.pdb

C:\ユーザー\ユーザー名\miniconda3\Library\bin へコピー

・IrfanViewのインストール
こちらは、ダウンロードしたインストーラを開いてインストールしてください。

◆OpenCVで車両検出
環境を構築したら、「OpenCV機械学習基礎知識」の項で説明したとおりの手順で教師あり学習をしていきます。

・正解画像の準備
精度を上げるためには7,000枚ほど必要とありますが、ここでは実験のため120枚程度を用意しました。
googleの画像検索から「自動車」「トラック」などのキーワードを基に、自動車の画像をダウンロードします。
様々なメーカーの自動車を、正面、側面、背面、斜めから写っているものを集めました。

集めた後、IrfanViewで画像に写っている車の矩形の位置と大きさを取得し、poslist.txtとして正解画像のリストを作成しました。

・不正解画像の準備
自動車以外が写っている画像を用意します。
車両走行中にノイズとして写るような画像、例えば、人間の写真、動物の写真、建物の写真、道路の写真、山や森などの風景の写真をgoogleの画像検索から240枚程度用意しました。

用意した後、不正解画像のリストをneglist.txtとして作成しました。

・ベクトルファイルを作成する
opencv_createsamplesを実行して、ベクトルファイルを生成します。
正解画像の枚数は119枚なので、-numには119を、Haar-Like特徴抽出の探索窓のサイズとして、-w 24 -h 24 を指定します。

opencv_createsamples.exe -info positive\poslist.txt -vec vec\positive.vec -num 119 -w 24 -h 24

・カスケード分類器を作成する
opencv_traincascadeを実行して、カスケード分類器を生成します。
正解画像のリストのパス、不正解画像のリストのパス、正解画像の個数、不正解画像の個数、Haar-Like特徴抽出の探索窓のサイズを指定します。
また、特徴量のタイプとして HAAR を、AdaBoostのタイプとして GAB を指定しました。

opencv_traincascade.exe -data cascade -vec vec\positive.vec -bg negative\neglist.txt -numPos 119 -numNeg 246 -w 24 -h 24 -featureType HAAR -bt GAB

すると、図のようにカスケード分類器の生成が始まります。

ステージ(カスケードされる分類器の1つ)は、0から19の20個生成され、それぞれの生成時間が表示されています。
最後の19ステージまで終わると、以下のようにトータルの生成時間が表示されます。筆者の環境だと1分25秒かかりました。

Training until now has taken 0 days 0 hours 1 minutes 25 seconds.

タスクマネージャでCPU使用率を見ると、平均で20~44%使用されていました。また、どのコアも満遍なく使われていました。逆に、GPU使用率は0~4%と、ほとんど使われていませんでした。

opencv_traincascadeを実行したパソコンのスペックは以下になります。パソコンの性能によって、実行時間は異なってきます。

OS:  Windows 10 Professional 64bit
CPU:  AMD Ryzen 7 4800H (基本属度:2.90GHz, コア数:8(論理プロセッサ数:16) L1キャッシュ:512KB L2キャッシュ: 4.0MB L3キャッシュ: 8.0MB)
GPU:  NVIDIA Geforce RTX 2060 (メモリ6.0GB)
メインメモリ: 16GB

※TIPS: “Required leaf false alarm rate achieved. Branch training terminated.”のメッセージが出た場合
探索窓のサイズを変えるなどパラメータを変えた場合、“Required leaf false alarm rate achieved. Branch training terminated.”といったメッセージが出る場合があります。
これは、指定したパラメータでの精度で誤検出が出なくなるまで学習したため、これ以上トレーニング不要という意味を示しています。この場合、最終的なカスケード分類器(cascade.xml)は生成されていますので、そのまま利用して構いません。

POS count : consumed 119 : 119
NEG count : acceptanceRatio 0 : 0
Required leaf false alarm rate achieved. Branch training terminated.

・カスケード分類器を基に、任意の画像から車を検出する
検出画像として、以下のimage8.pngという画像を用意しました。

test.pyファイルのファイル名を対象画像のファイル名に変更します(test.pyのあるフォルダからの相対パスで指定します)。

show_cascaded_image( 'images/image8.png', 'data/cars/cascade/cascade.xml' )

そして、test.pyを実行します。

以下のように、検出した車両に緑色の検出枠が表示されました。

◆まとめ
他の画像でもいろいろ試してみましたが、120枚程度の正解画像だと車両と無関係の箇所に検出枠が表示されるなど、誤検出が目立ちました。精度を上げるためには正解画像の枚数を増やしたり、いろんな車種の車両を様々な角度から写したものを用意するなどの対策が考えられます。
今回実験したのは教師あり学習でしたが、次回はCNNなどの教師なし学習(ディープラーニング)も試して、比較できたらと思います。

◆参考文献
OpenCVによるAIの実装方法
機械学習まであと1歩!写真から顔や物体を取り出すには? 実装編第2回
OpenCVで機械学習をさせてみた!! 実装編第3回
OpenCV公式ドキュメント cascade classifier チュートリアル
OpenCV公式ドキュメント user guide traincascade
opencv_createsamplesとopencv_traincascadeについて
OpenCV公式ドキュメント カスケード型分類器
OpenCVの勉強③(分類器を作成してみる)
Data Augmentationに使えるopencv_createsamplesの使い方
Rapid Object Detection With A Cascade of Boosted Classifiers Based on Haar-like Features
opencv_createsamplesとopencv_traincascadeについて
OpenCVで物体検出器を作成する⑤ ~createsamples~
OpenCVで物体検出器を作成する⑥ ~traincascade~
ブースティング入門
【入門者向け解説】openCV顔検出の仕組と実践(detectMultiScale)
グレースケール化 cvtColor()

関連記事