利用opencv訓練分類器

一、簡介

       目標檢測方法最初由PaulViola提出,並由Rainer Lienhart對這一方法進行了改善。該方法的基本步驟爲: 首先,利用樣本(大約幾百幅樣本圖片)的harr 特徵進行分類器訓練,得到一個級聯的boosted分類器。分類器中的"級聯"是指最終的分類器是由幾個簡單分類器級聯組成。在圖像檢測中,被檢窗口依次通過每一級分類器, 這樣在前面幾層的檢測中大部分的候選區域就被排除了,全部通過每一級分類器檢測的區域即爲目標區域。

        分類器訓練完以後,就可以應用於輸入圖像中的感興趣區域的檢測。檢測到目標區域分類器輸出爲1,否則輸出爲0。爲了檢測整副圖像,可以在圖像中移動搜索窗口,檢測每一個位置來確定可能的目標。 爲了搜索不同大小的目標物體,分類器被設計爲可以進行尺寸改變,這樣比改變待檢圖像的尺寸大小更爲有效。所以,爲了在圖像中檢測未知大小的目標物體,掃描程序通常需要用不同比例大小的搜索窗口對圖片進行幾次掃描。

目前支持這種分類器的boosting技術有四種:Discrete Adaboost, Real Adaboost, Gentle Adaboost and Logitboost。"boosted"即指級聯分類器的每一層都可以從中選取一個boosting算法(權重投票),並利用基礎分類器的自我訓練得到。

根據上面的分析,目標檢測分爲三個步驟:

1、 樣本的創建

2、 訓練分類器

3、 利用訓練好的分類器進行目標檢測

二、樣本的創建

訓練樣本分爲正例樣本和反例樣本,其中正例樣本是指待檢測的目標樣本,反例樣本指其它任意圖片。
反例(負)樣本:負樣本可以來自於任意的圖片,但這些圖片不能包含目標特徵。負樣本由背景描述文件來描述。背景描述文件是一個文本文件,每一行包含了一個負樣本圖片的文件名(基於描述文件的相對路徑)。該文件創建方法如下:

在Dos命令下,可以生成描述文件,具體方法是在Dos下的進入你的圖片目錄,比如我的圖片放在D:\face\negdata下,則:

在開始菜單的查找框中輸入cmd,然後運行程序,輸入cmd打開DOS命令窗口,輸入d:回車,再輸入cd D:\face\negdata進入圖片路徑,再次輸入dir/b > negdata.dat,則會圖片路徑下生成一個negdata.dat文件,打開該文件將最後一行的negdata.dat刪除,這樣就生成了負樣本描述文件。

也可以直接寫一個negdata.bat文件,.bat是一個windows批處理文件,裏面的內容如下:

cd D:\face\negdata
dir /b > negdata.dat
pausedos

雙擊可直接執行裏面的內容,生成負樣本的描述文件。

命令窗口結果如下圖:

正樣本:

對於正樣本,通常的做法是先把所有正樣本裁切好,並對尺寸做規整(即縮放至指定大小),如上圖所示:

我這裏是縮放成20*20大小,由於HaarTraining訓練時輸入的正樣本是vec文件,所以需要使用OpenCV自帶的CreateSamples程序,據我所知,早期版本的opencv好像自帶編譯好的createsamples.exe,但後期版本需要自己編譯一下,才能形成creatsamples.exe,編譯方法如下:新建一個項目,在項目中添加opencv自帶的creatsamples.cpp文件,運行程序就會有.exe文件生成。例如,我新建項目first,就會有一個first.exe生成,這個first.exe在工程項目裏面,opencv的createsamples.cpp在opencv\apps\haartraining路徑下可以找到。

1) 製作一個正樣本描述文件,用於描述正樣本文件名(包括絕對路徑或相對路徑),正樣本數目以及各正樣本在圖片中的位置和大小。典型的正樣本描述文件如下:

同樣它的生成方式可以用負樣本描述文件的生成方法,最後用txt的替換工具將“jpg”全部替換成“jpg 1 0 0 20 20“,就可以了,如果你的樣本圖片多,用txt替換會導致程序未響應,你可以將內容拷到word下替換,然後再拷回來。jpg後面那五個數字分別表示圖片個數,目標的起始位置及其寬高。這樣就生成了正樣本描述文件posdata.dat。

2) 運行first.exe,如果直接在Vs環境下運行,可以在Project\Settings\Debug屬性頁的Programarguments欄設置運行參數。下面是一個運行參數示例:
-info D:\face\dst\src.dat -vec D:\face\pos.vec -num 80 -w 20 -h 20
表示有80個樣本,樣本寬20,高20,正樣本描述文件爲src.dat,結果輸出到pos.vec,這些文件前面是我存放這些文件的路徑,讀者應根據自己的實際情況做修改。

或者在dos下輸入:

"F:\opencvworkspace\first\Debug\first.exe" -info D:\face\dst\src.dat -vec D:\face\pos.vec -num 80 -w 20 -h 20
運行完了會D:\face下生成一個*.vec的文件。該文件包含正樣本數目,寬高以及所有樣本圖像數據。結果入下圖:

Createsamples程序的命令行參數:
命令行參數:
-vec <vec_file_name>
訓練好的正樣本的輸出文件名。
-img<image_file_name>
源目標圖片(例如:一個公司圖標)
-bg<background_file_name>
背景描述文件。
-num<number_of_samples>
要產生的正樣本的數量,和正樣本圖片數目相同。
-bgcolor<background_color>
背景色(假定當前圖片爲灰度圖)。背景色制定了透明色。對於壓縮圖片,顏色方差量由bgthresh參數來指定。則在bgcolor-bgthresh和bgcolor+bgthresh中間的像素被認爲是透明的。
-bgthresh<background_color_threshold>
-inv
如果指定,顏色會反色
-randinv
如果指定,顏色會任意反色
-maxidev<max_intensity_deviation>
背景色最大的偏離度。
-maxangel<max_x_rotation_angle>
-maxangle<max_y_rotation_angle>,
-maxzangle<max_x_rotation_angle>
最大旋轉角度,以弧度爲單位。
-show
如果指定,每個樣本會被顯示出來,按下"esc"會關閉這一開關,即不顯示樣本圖片,而創建過程繼續。這是個有用的debug選項。
-w<sample_width>
輸出樣本的寬度(以像素爲單位)
-h《sample_height》
輸出樣本的高度,以像素爲單位。
到此,前期的正負樣本就準備好了,下面是訓練分類器。

三、訓練分類器

樣本創建之後,接下來要訓練分類器,這個過程是由haartraining程序來實現的。該程序源碼由OpenCV自帶,和Createsamples一樣,早期opencv版本有自帶的haartraining.exe,這裏也需要自己編譯,例如:我新建項目second,添加opencv\apps\haartraining中的haartraining.cpp文件,可以生成一個second.exe。同樣在它的Project\Settings\Debug屬性頁的Programarguments欄設置運行參數,可以完成分類器的訓練。例如:

-data D:\face\cascade -vec D:\face\pos.vec -bg D:\face\negdata\negdata.dat -npos  80 -nneg 350 -mem 200 -mod ALL -w 20 -h 20

cascade代表分類器的名字,pos.ves代表正樣本,negdata.dat代表負樣本,-pos代表正樣本個數,-nneg代表負樣本個數,-mem代表分配內存數,-mod ALL代表使用垂直和45度角旋轉特徵,-w和-h代表圖片的寬高,注意,正樣本數量和負樣本數量最好控制在1:4至1:5之間的比例爲好。訓練好以後會在D:\face\cascade生成生成一些子目錄,這些子目錄裏包含txt文檔,這些文檔即爲訓練好的分類器。訓練結果如圖所示:


訓練好的分類器:文件夾0裏面的部分內容:

Haartraining的命令行參數如下:
-data<dir_name>
存放訓練好的分類器的路徑名。
-vec<vec_file_name>
正樣本文件名(由trainingssamples程序或者由其他的方法創建的)
-bg<background_file_name>
背景描述文件。
-npos<number_of_positive_samples>,
-nneg<number_of_negative_samples>
用來訓練每一個分類器階段的正/負樣本。合理的值是:nPos= 7000;nNeg = 3000
-nstages<number_of_stages>
訓練的階段數。
-nsplits<number_of_splits>
決定用於階段分類器的弱分類器。如果1,則一個簡單的stumpclassifier被使用。如果是2或者更多,則帶有number_of_splits個內部節點的CART分類器被使用。
-mem<memory_in_MB>
預先計算的以MB爲單位的可用內存。內存越大則訓練的速度越快。
-sym(default)
-nonsym
指定訓練的目標對象是否垂直對稱。垂直對稱提高目標的訓練速度。例如,正面部是垂直對稱的。
-minhitrate《min_hit_rate》
每個階段分類器需要的最小的命中率。總的命中率爲min_hit_rate的number_of_stages次方。
-maxfalsealarm<max_false_alarm_rate>
沒有階段分類器的最大錯誤報警率。總的錯誤警告率爲max_false_alarm_rate的number_of_stages次方。
-weighttrimming<weight_trimming>
指定是否使用權修正和使用多大的權修正。一個基本的選擇是0.9
-eqw
-mode<basic(default)|core|all>
選擇用來訓練的haar特徵集的種類。basic僅僅使用垂直特徵。all使用垂直和45度角旋轉特徵。
-w《sample_width》
-h《sample_height》
訓練樣本的尺寸,(以像素爲單位)。必須和訓練樣本創建的尺寸相同。

四、利用訓練好的分類器進行目標檢測

這一步需要用到performance.exe,該程序源碼由OpenCV自帶,也需要我們新建項目,自己編譯一遍,例如:我新建項目third,添加opencv\apps\haartraining中的performance.cpp文件,可生成third.exe。同樣在它的Project\Settings\Debug屬性頁的Programarguments欄設置運行參數,可以完成分類器的目標檢測。在這之前,必須準備好你的測試圖片,格式和你的正樣本圖片一樣,尺寸也和正樣本圖片一樣。在Programarguments欄設置運行參數,例如:

-data D:\face\cascade -info D:\face\testdata\testdata.dat -w 20 -h 20 -rs 30

然後就可以的得到測試結果。

performance的命令行參數如下:

Usage:./performance
-data <classifier_directory_name>
-info <collection_file_name>
[-maxSizeDiff <max_size_difference = 1.500000>]
[-maxPosDiff <max_position_difference = 0.300000>]
[-sf <scale_factor = 1.200000>]
[-ni]
[-nos <number_of_stages = -1>]
[-rs <roc_size = 40>]
[-w <sample_width = 24>]
[-h <sample_height = 24>]

也可以用opencv的cvHaarDetectObjects函數進行檢測。







發佈了36 篇原創文章 · 獲贊 22 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章