Tensorflow環境構築手順

やっとUbuntuにTensorflowがインストールできたので防備録的に手順を。

概ね手順はここ(https://qiita.com/konzo_/items/3e2d1d7480f7ef632603)通りである。

まずPCの環境。
CPU:Core i5 9400F
GPU:GeForce RTX 2060
OS:Ubuntu 18.04
python:3.6.7

インストールしたもの。
Nvidiaビデオドライバ:410.104
CUDA:10.0
CuDNN:7.4.1
tensorflow:tensorflow-gpu 1.13.1

1.環境の更新

2.gitのインストール

3.ビデオドライバのインストール

CUDAやTensorflowと合わせる必要があるため、今回は410を入れる。

3.1.nouveauグラフィックドライバの無効化

コマンドを打って何も表示されなければ何もせず。リストが表示されればnouveauドライバを無効にする。

3.2.ビルドツールのインストール

参考元にはなぜやるのかわからないとあるが、いずれ入れることになるのでこのタイミングで入れておく。

3.3.NVIDIAグラフィックドライバのインストール

再起動したらインストール確認

表が表示され、ドライバのバージョンが表示されるので確認する。

4.CUDAのインストール

NVIDIAの公式サイト(https://developer.nvidia.com/cuda-toolkit-archive)からダウンロードしてくる。
NVIDIAのトップページからCUDAを辿っていくと10.1のダウンロードに行き着くので、ここでLegacy Releasesを選択してArchiveからダウンロード。

そしてdebファイルをダウンロードしてコマンド実行。

末尾に2行追加。

再起動して、CUDAのインストール確認

5.cuDNNのインストール

CUDA同様、NVIDIAの公式サイト(https://developer.nvidia.com/cudnn)からダウンロードする。
ログインして、質問に答えて、使用許諾の同意にチェックをつけるとダウンロードができるが、今回は7.4をインストールしたいので、Archived cuDNN Releasesを選択してアーカイブからダウンロードを行う。
7.4は7.4.1と7.4.2があるが、今回は7.4.2を選択。7.4.2のCUDAバージョンが10.0のリンクを選択。

Ubuntu18.4の次の2つをダウンロードする。
・Runtime
・Developer Library
必要であればコードサンプルとドキュメントもダウンロードすればよい。
・Code Samples and User Guide

ダウンロード後、ダウンロードフォルダに移動してインストール。

6.tensorflow-gpu 1.13.1のインストール

anacondaやvirtualenvは使わないのでそのままインストールする。

pip3が使えない場合は先にこのコマンド。

7.確認

エラーがでなければ成功!

ここまでの手順がはっきりするまで、結構大変でした。

Tensorflowの導入

UbuntuにDeepLearningの環境を構築する。

CPU:Core i5 9400F
GPU:GeForce RTX 2060

NVIDIA Driver:418
CUDA:10.1
cuDNN:7.4
Tensorflow:tensorflow-gpu1.13.0

しかし、何度インストールを試みてもうまくインストールできない。
原因がわからないが調べていくうちに原因がわかってきた。

ここに(https://qiita.com/konzo_/items/a6f2e8818e5e8fcdb896)原因が整理されていた。
GPUのドライバは最新の418が入れられるのだが、tensorflow-gpu1.13.0が対応しているのはCUDA10.0。CUDA10.1には対応していないということだ。

本当にこういう記事は助かります。

明日再びTensowFlow環境の構築を最初からしてみよう。

Ubuntu 19.04へのアップグレード

Ubuntu18.04LTSを使用していたが、19.04が出たと言うことで早速アップグレードを試してみた。
ソフトウェアとアップデート画面から、Ubuntuの新バージョンの通知をすべての新バージョンに変更してソフトウェアの更新を行った見たところ、18.10へのアップグレードができるようだ。
なのでアップグレードができる18.10へそのままアップグレードを試してみたところ、、、一通りインストールが終わり再起動したらプロンプトが表示されたまま起動が進まなくなってしまった。

この手順はtensorflowなどを一通り入れてからも、18.04をクリーンインストールした直後でも同じだったので、自分の環境では合わないらしい。
コマンドでアップグレードを行ったところこれはうまく行った。ソフトウェアとアップデート画面からのアップグレードがうまく行かなかったのは単純に途中の質問の答え方がまずかっただけかもしれない。
調子に乗って19.04へのアップグレードも行ったのだが、これもまたうまく行かなかった。

しかしUbunutは安定した環境での利用が前提でインストールしているので、結局は18.04LTSでの使用に戻すことになる。

Ubuntu 18.4 LTS の導入

PCのCPUからビデオカードまでを一新したので、Windows10だけでなくUbuntuのインストールもしてデュアルブートにした。

PCの環境
・CPU:Core i5 9400F
・メモリ:16G
・ビデオ:RTX2060
・マザー:MSIのマザー

WindowsとUbuntuのインストールまでは問題なく行えたが、PCをブートしても何故かGRUBが起動せず毎回Windowsが起動してしまう。

とりあえず大事なのは、
・BIOSをUEFIにする
・セキュアブートは切る
・ブートローダーにインストール先はWindows Boot Managerとは別にする

これは環境によっても違うので参考程度に。

何度かパーティションを切り直したりブートローダーのインストール先を切り替えたりBIOSの設定画面でUEFIのブート順を見直して、無事デュアルブートが成功。

OpenCV 物体検出、分類器作成と検出テスト その3

OpenCVの家紋の物体検出をするための分類器をその2で作成しました。
ここではその分類器を使って検出をしてみます。

まずは、学習に使用した正解画像の中から何枚か選んで。

いい感じで検出できていますね。4枚目はひし形の枠は外れてしまいましたが、十分許容範囲かと思います。
そもそも学習に使用した画像なので、これで検出されないと困ってしまいますが。

 

続いて、学習には使用していないテスト画像で検出確認。


素晴らしい検出結果ですね


これも良いです。左右の家紋は切れていたりかぶっていたりで検出できなかったようです


提灯の家紋が検出できず、傘の中央部分が家紋と判断されています。
傘についている小さい家紋はバッチリです。
提灯のは角度がつきすぎているのが検出できない原因でしょうね。


全てではありませんが、かなり検出できていますね。


左二つは検出できました。その隣も検出して欲しかったのですが。


中央の金ピカのは検出されませんでした。右側のは確かに家紋っぽい。

 

今回60種類の家紋を学習させましたが、テスト画像内の家紋は学習に使用していない家紋ばかりです。にも関わらず家紋というものの特徴をよく捉えて判断しているのがわかります。
私の環境で、1920×1500サイズの画像検出の処理時間は900msから1300ms、小さい640×480程度の画像は300ms程度でした。パラメータによって制限をつけることで処理時間を短くすることも可能です。

 

次は検出してほしかったのに検出できなかったテスト画像。


角度が大事ですね。
ですが、これは角度をつけた画像を学習をさせることで十分検出できるようになると思います。

 

最後に家紋が含まれない画像。


1枚目の画像は女性の服の模様が家紋ですね、検出されてしまいました。
それ以外は標識だったりマークだったりを誤検出していません。
なかなかの結果だと思います。

 

次回交通標識で分類器作成の機会学習をやってみたいと思います。
最近ホンダで代車を借りたところ、走行中にインパネ部分に標識が表示されました。速度標識や追い越し禁止などが表示されます。

面白かったのでこれを作ってみたいと思います。

 

OpenCV 物体検出、分類器作成と検出テスト その2

その1で分類器によって物体検出ができることがわかりましたので、その分類器を作成してみます。

分類器作成にはポジティブ画像(正解画像)とネガティブ画像(不正解画像)が必要です。実用的な精度にはポジティブ画像7000枚、ネガティブ画像3000枚が必要とか言われていますが、実際その枚数揃えるのは結構大変です。特にポジティブ画像。
そこで、OpenCVでは1枚の正解画像から複数枚の画像を生成する機能ががあります(角度や大きさを変えて生成してくれます)。これを使えば、例えば50枚の正解画像を用意してそれぞれから128枚を自動生成それば6400枚に増やすことができますね。

ではさっそく、家紋の分類器を作成してみます。

家紋は非常にたくさんの種類があります。全部集めるのは大変なので適当に60種類ほど正解画像を作成してみました。
あまり小さいと検出精度が上がらなかったので、今回は87×87のサイズで用意しました。
輪郭より外側は白で塗りつぶしています。自動生成で枚数を増やす時にネガティブ画像上に貼り合わせるのですが、その時にこの白色が透過色となります。

ネガティブ画像はなんでも良いのですが、正解画像が含まれていない画像を用意します。風景、室内、建物、PC、動物など適当な画像です。

白黒画像になっていますがカラーで良いです。
画像サイズは640×480、320×240、1280×700などさまざまです。これを3000枚用意しました。

フォルダを3つ用意し「OpenCV」フォルダにOpenCVのコマンド、「Positives」フォルダにポジティブ画像、「Negatives」フォルダにネガティブ画像を格納しました。全部同一の階層に作成しています。

OpenCVTest
+ OpenCV
+ Positives
+ Negatives

ネガティブ画像は画像リストが必要となるので事前に作成しておきます。
コマンドプロンプト画面を表示し、Negativesフォルダに移動して次のコマンドで画像リストを作成します。

dir /B > negatives.txt


これでネガティブ画像のリストができました。

つづいてポジティブ画像を増やしていきます。
OpenCVフォルダに移動して、コマンドプロンプトで次のコマンドを入力します。ポジティブ画像はPositive001.jpgからPositive060.jpgまで連番で用意しました。

opencv_createsamples.exe -img ..¥Positives¥Positive001.jpg -bg ..¥Negatives¥negatives.txt -info ..¥Positives¥cropp001.txt -num 128 -maxxangle 0.5 -maxyangle 0.5 -maxzangle 0.3 -bgcolor 255 -bgthresh 8 -w 48 -h 48

-imgには用意したポジティブ画像を。-infoには生成した画像の一覧の出力先ファイル名を。-bgはネガティブ画像のリストファイル。-numは生成する画像の枚数。-maxxangleと-maxyangleと-maxzangle生成時にどの程度回転させるかを。-bgcolorはポジティブ画像の背景色で、255が白、0が黒。-bgthreshは透過度です。0が100%透過。
成功すると、ネガティブ画像上にポジティブ画像の角度や大きさを変えた画像が生成されます。

また、その画像の一覧のファイルも作成されます。

生成されたポジティブ画像の一覧ファイルはネガティブ画像のと違い、スペース区切りのCSVファイルとなります。ファイル名の後ろは正解画像部分の数、その開始位置X、開始位置Y、幅、高さ、です。この部分は自動で生成されるので特に修正などする必要はないです。

用意したポジティブ画像ぶん、-imgと-infoのファイル名部分を変えながら全て行います。

たまにですが、ポジティブ画像の自動生成を行うと次のエラーが出る場合があります。

OpenCV Error: Incorrect size of input array () in cvGetSubRect, file C:\Tools\opencv3.2\sources\modules\core\src\array.cpp, line 1275

その際は、このコマンドを実行するときだけネガティブ画像のリスト件数を作成する画像数(ここでは128)に減らして実行するとエラーが出にくくなります。

全てのポジティブ画像を増やし終わったら、作成されたポジティブ画像の一覧ファイルを結合します。この手順ではcropp001.txt からcropp060.txtまで作成されているので、コマンドプロンプトでポジティブ画像のフォルダ(Positives)に移動して次のコマンドで結合します。

type cropp*.txt > positives.txt

結合されたpositives.txtには60×128で7680行のポジティブ画像のデータが記録されているはずです。

 

続いて、ベクトルファイルを生成します。

が、その前に作成するベクトルファイルと分類器を格納するフォルダを作成しておきます。OpenCVフォルダに「vector」フォルダと「cascade」フォルダを作成します。

ベクトルファイルの作成もopencv_createsamplesコマンドを使用します。コマンドプロンプトからOpenCVのフォルダに戻って次のコマンドを入力します。

opencv_createsamples.exe -info ..¥Positives¥positives.txt -bg ..¥Negatives¥negatives.txt -vec .¥vector¥croppkamon.vec -num 7680 -w 48 -h 48

-numにはポジティブ画像の枚数を指定しますので、Positives.txtのデータ数を設定します。

成功すると次が表示されます。このコマンドは数分でおわります。
Done. Created 7680 samples

 

最後に分類器の作成です。
ここまでの手順が長かったですが、このコマンドは実行時間はさらに長いです。

opencv_traincascade.exe -data .\cascade -vec .\vector\croppkamon.vec -bg ..\Release\Wrong\negatives.txt -numPos 6500 -numNeg 3019 -numStages 20 -precalcValBufSize 1024 -precalcIdxBufSize 1024 -featureType LBP -minHitRate 0.995 -maxFalseAlarmRate 0.5 -w 48 -h 48

-numPosはポジティブ画像の枚数を指定しますが、用意した数の80%から90%程度を指定してください。ポジティブ画像として妥当ではないと判断された時に除外されるようです。-numNegはネガティブ画像の枚数です。-featureTypeはHAARかLBPかHOGを指定します。それぞれ特徴の抽出の仕方が異なります。

実行した際に次のエラーが出てしまった場合、
Train dataset for temp stage can not be filled. Branch training terminated.
Cascade classifier can’t be trained. Check the used training parameters.
ネガティブ画像のリストを修正します。いまはファイル名だけのリストになっていますので、これを全てフルパスにします。

正しくコマンドが開始されると、次のような感じで学習が始まります。

PARAMETERS:
cascadeDirName: .\cascade
vecFileName: .\vector\croppkamon.vec
bgFileName: ..\Negatives\negatives.txt
numPos: 6500
numNeg: 3019
numStages: 20
precalcValBufSize[Mb] : 1024
precalcIdxBufSize[Mb] : 1024
acceptanceRatioBreakValue : -1
stageType: BOOST
featureType: LBP
sampleWidth: 48
sampleHeight: 48
boostType: GAB
minHitRate: 0.995
maxFalseAlarmRate: 0.5
weightTrimRate: 0.95
maxDepth: 1
maxWeakCount: 100
Number of unique features given windowSize [48,48] : 141376

===== TRAINING 0-stage =====
<BEGIN
POS count : consumed 6500 : 6500
NEG count : acceptanceRatio 3019 : 1
Precalculation time: 30.424
+—-+———+———+
|  N |    HR |     FA |
+—-+———+———+
|  1 |       1 |       1 |
+—-+———+———+
|  2 |       1 |       1 |
+—-+———+———+

0ステージ目の学習が開始ししました。これが19ステージまで完了するとカスケード分類器がcascadeフォルダに作成されています。ファイル名は「cascade.xml」です。
このコマンドは途中で中止しても、同じコマンドを実行すれば続きから学習させることができます。もし、最初からやり直したい場合は、cascaseフォルダに作成されたXMLファイルを全て削除してから行って下さい。

 

ちなみに私のチープな環境でコマンドが終了した時の最後の出力内容。

+—-+———+———+
| 16| 0.995143| 0.501491|
+—-+———+———+
| 17| 0.995286| 0.480623|
+—-+———+———+
END>
Training until now has taken 0 days 14 hours 23 minutes 2 seconds.

14時間30分ほどかかりました。。

次回は作成された家紋のカスケード分類器を使用して検出確認をしてみます。

 

 

OpenCV 物体検出、分類器作成と検出テスト その1 

OpenCVを使った物体検出の分類器作成をしたので、その手順や所感をまとめてみました。

物体を検出させるにはカスケード分類器を作成します。
カスケード分類器はポジティブ画像(正解画像)とネガティブ画像(不正解画像)から特徴を抽出して、機械学習によって作成されます。そして、作成された分類器を使用することで簡単に物体検出ができます。勿論きちんと学習できていないと精度は期待できませんが。。

さて、公開されている分類器があるので、まずはそれを使って顔や体の検出を試してみます。

まず顔の分類器(haarcascade_frontalcatface.xml)で確認。
検出にはOpenCVのAPI、detectMultiScaleを使います。


そこそこいい感じですね。
パラメータは全てデフォルトなので、多少調整してみます。
ここでは、minNeighborsをデフォルト値の3から10に変更してみます。


誤検出は減りましたが、正しく検出されていた顔も検出されなくなりました。
こういった検出精度のパラメータはトレードオフなので設定が難しいところです。

 

C#ソースコード/フォームアプリ/PictureBoxを配置/OpenCvSharp3

Mat originalMat = new Mat(“./img/img2.jpg”);
CascadeClassifier fil = new CascadeClassifier(“./cascade/haarcascade_frontalface_default.xml”);

// グレー変換
Mat gray = new Mat();
Cv2.CvtColor(originalMat, gray, ColorConversionCodes.BGR2GRAY);

// 検出
Rect[] rects;
rects = fil.DetectMultiScale(gray, 1.1, 10);

// 枠描画
foreach (Rect rc in rects)
{
originalMat.Rectangle(rc, new Scalar(0, 0, 255), 2);
}

Bitmap bmp = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(originalMat);
Graphics g = Graphics.FromImage(bmp);
g.DrawImage(bmp, 0, 0);

g.Dispose();

pictureBox1.Image = bmp;