延續上一篇Manually Compiling and Installing OpenCV on Mac / Windows Without Package Manager,假設讀者已安裝OpenCV開發環境與command line指令設定。此篇以 Tutorial: OpenCV haartraining (Rapid Object Detection With A Cascade of Boosted Classifiers Based on Haar-like Features) 和 Creating a haar cascade classifier aka haar training 為基礎撰寫。

偵測物圖片蒐集

首先,要偵測的物體圖片是少不了的。假設我們要偵測的是一個原子筆,那需要很多張像下圖一樣的圖片,裁割到剩下目標物(越多張越好),把這些當做我們Training時的Positive Images。

另外,還需要大量的Negative Images,也就是沒有包含任何目標物部分的圖片,如下圖。

裁割圖片可以使用一套叫做imageclipper的軟體。

產生相關檔案與結構

到這裡,我們的檔案結構應該會有三個資料夾:Positive_Images, Negative_Images, Samples(此篇的圖片副檔名都以jpg為主)。
  • Positive_Images:用來存放上面裁割過後只剩下目標物的圖片。
  • Negative_Images:存放沒有包含任何目標物部分的圖片,也就是不能包含任何原子筆相關部分在內(就算是鉛筆的部份也不要)。
  • Samples:空資料夾,用來存放等等產生用來Training的檔案。
  • 然後,為了讓training知道我們有哪些檔案,我們必須要建立一個文件,裡面有Positive、Negative的圖片位址。另外,記得Positive Image的大小必須要一樣,若是有安裝imagemagick,可以使用像這樣"mogrify -resize ???x??? *.jpg"的指令。

find Positive_Images -name "*.jpg" > positives.dat

find Negative_Images -name "*.jpg" > negatives.dat

產生Training Samples

下載網路上別人寫好的perl scripts:createtrainsamples.pl 及 mergevec.cpp。mergevec.cpp是用來將perl scripts產生出來的sample轉成haartraining需要的vec格式。 ### 編譯mergevec.cpp成可執行檔 將mergevec.cpp複製到opencv source code的apps/haartraining內,裡面有編譯時所需的cpp檔案。

g++ `pkg-config --cflags opencv` `pkg-config --libs opencv` -o mergevec mergevec.cpp cvboost.cpp cvcommon.cpp cvsamples.cpp cvhaarclassifier.cpp cvhaartraining.cpp

若出現找不到header files的errors

mergevec.cpp:7:28: error: cvhaartraining.h: No such file or directory

mergevec.cpp:8:47: error: _cvhaartraining.h: No such file or directory


那就是在安裝opencv時,沒有把apps/haartraining內的所有*.h複製到/usr/local/include/opencv/.內。

若出現Undefined symbols這種沒有定義的錯誤

Undefined symbols for architecture x86_64: "icvGetHaarTraininDataFromVecCallback(CvMat*, void*)", referenced from: icvAppendVec(CvVecFile&, CvVecFile&, int*, int, int)in cc7bmOx6.o "icvWriteVecSample(__sFILE*, void*)", referenced from: icvAppendVec(CvVecFile&, CvVecFile&, int*, int, int)in cc7bmOx6.o "icvWriteVecHeader(__sFILE*, int, int, int)", referenced from: icvMergeVecs(char*, char const*, int, int, int)in cc7bmOx6.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit sta
是mergevec在呼叫icvAppendVec、icvMergeVecs時鏈結不到function,原因有兩種可能:第一,沒有把mergevec.cpp複製到apps/haartraining內編譯,但這錯誤應該一開始在下g++時就會有錯誤;第二,你的g++少了幾個cpp檔案參數

完成編譯mergevec以及下載perl script完成後,鍵入以下指令


perl createtrainsamples.pl positives.dat negatives.dat samples 7000 "opencv_createsamples -bgcolor 0 -bgthresh 0 -maxxangle 1.1 -maxyangle 1.1 maxzangle 0.5 -maxidev 40 -w 300 -h 120"

find Samples/ -name '*.vec' > samples.dat # to create a collection file for vec files

mergevec samples.dat samples.vec

*注意:positive跟negative內的圖片大小與指令參數的w, h需一致,否則會有"Invalid background description file."的錯誤

參數說明

  • Samples後面接的7000:代表要利用提供的positive和negative圖像產生多少個sample,數目不足的部份這個perl script會幫我們做些distortion來產生(這也是為什麼要用別人寫的perl script)。另外,在opencv source code內的haartraining doc內有說,positive最好的sample數量為7000。
  • w, h:為positive每張影像的寬、高

產生Test Samples

一樣,先下載perl script:createtestsamples.pl

perl createtestsamples.pl positives.dat negatives.dat Samples 7000 "opencv_createsamples -bgcolor 0 -bgthresh 0 -maxxangle 1.1 -maxyangle 1.1 maxzangle 0.5 -maxidev 40 -w 20 -h 20"

find tests/ -name 'info.dat' -exec cat \{\} \; > tests.dat # merge info files

Haar Training

```

opencv_haartraining -data haarcascade -vec samples.vec -bg negatives.dat -nstages 20 -nsplits 2 -minhitrate 0.999 -maxfalsealarm 0.5 -npos 7000 -nneg 3019 -w 300 -h 120 -nonsym -mem 512 -mode ALL


參數說明
<ul>
	<li><span style="line-height: 22px;">-nonsym:偵測物體左右不是對稱的(若是像臉這種有對稱特性的則可不用加,預設即是對稱性,可以加速處理速度,這樣haar-like features上就只要處理左半部或是右半部)
</span></li>
	<li><span style="line-height: 22px;">-mode ALL:使用直立與45度角的haar-like features,預設是basic只使用直立feature</span></li>
	<li><span style="line-height: 22px;">-data:haartraining的輸出資料夾名稱</span></li>
	<li><span style="line-height: 22px;">-mem:要分配多少記憶體(MB)給haartraining使用</span></li>
	<li><span style="line-height: 22px;">w, h:同上,即為positive的圖像寬、高。</span></li>
</ul>
<span style="line-height: 22px;">***在7000個samples、20個stages以及本篇的參數設定下,training保守估計需要三天的時間。</span>
<h2><span style="color: #3366ff;">Generate a XML File</span></h2>
首先需要編譯OpenCV Source Code內的convert_cascade.c這個檔案(在OpenCV/samples/c/convert_cascade.c),編譯好後複製回我們Training的資料夾下。

gcc pkg-config --cflags opencv pkg-config --libs opencv -o convert_cascade convert_cascade.c

### 產生XML

./convert_cascade --size="300x120" haarcascade haarcascade.xml


*注意,大小要跟前面positive與sample一樣

更多詳細的指令介紹可以參考本篇文章的Reference。
<h2><span style="color: #3366ff;">Reference</span></h2>
<ul>
	<li><span style="line-height: 22px;"><a href="http://note.sonots.com/SciSoftware/haartraining.html" target="_blank">Tutorial: OpenCV haartraining (Rapid Object Detection With A Cascade of Boosted Classifiers Based on Haar-like Features)</a></span></li>
	<li><span style="line-height: 22px;"><a href="http://opencvuser.blogspot.tw/2011/08/creating-haar-cascade-classifier-aka.html" target="_blank">Creating a haar cascade classifier aka haar training</a></span></li>
	<li><a href="http://note.sonots.com/SciSoftware/haartraining/mergevec.cpp.html" target="_blank">mergevec.cpp</a></li>
	<li><a href="http://docs.opencv.org/trunk/doc/user_guide/ug_traincascade.html" target="_blank">Cascade Classifier Training</a></li>
</ul>