【圖像處理】Haar Adaboost 檢測自定義目標(視頻車輛檢測算法代碼)

閱讀須知

本博客涉及到的資源:git

正樣本:http://download.csdn.net/detail/zhuangxiaobin/7326197算法

負樣本:http://download.csdn.net/detail/zhuangxiaobin/7326205app

訓練和檢測工具:http://download.csdn.net/detail/zhuangxiaobin/7414793工具

分類器xml文件:http://download.csdn.net/detail/zhuangxiaobin/7553415oop

adaboost訓練和測試源代碼:http://download.csdn.net/detail/zhuangxiaobin/7590517測試

 

更新總結:http://blog.csdn.net/zhuangxiaobin/article/details/40432705ui

 

       在開始閱讀以前,建議先把這幾個用到的資料先下載了,有很多網友想要訓練的代碼,我沒有直接提供,因此也沒必要私信我提供代碼了。若是非要弄懂整個過程的話,有兩種途徑。一種是經過cmake opencv查看源代碼(事實上本工具也是經過這種途徑獲得的),另外一種就是下載adaboost訓練和測試的源代碼而後本身能夠選擇本身想要的特徵,這對於想作特徵融合的網友是比較有幫助的,算法的介紹能夠經過點擊AdaBoost算法詳解查看。spa

       本文章的目的是讓全部在數字圖像處理零經驗的同窗能夠快速實現運動目標跟蹤。.net

 

                                           Haar Adaboost 檢測自定義目標(視頻車輛檢測算法代碼)

 

       opencv自帶了一我的臉識別用到的分類器,咱們直接使用就好了。可是不少人想到要跟蹤其餘東西,例如說,手,杯子,籃球,汽車,那怎麼辦?其實很簡單,只要按照一下步驟一步一步作,很容易就能夠作到了。運動目標識別,用上這個工具,貌似都不是什麼難事。(好像在賣廣告了。。)回到正題,本文用的是haar+adaboost的方法。code

目標檢測分爲三個步驟:

一、 樣本的建立

二、 訓練分類器

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

一.樣本的建立:    

訓練樣本分爲正例樣本和反例樣本。正例樣本是指待檢目標樣本(例如可樂瓶,汽車,人臉等),反例樣本指其它任意圖片,全部的樣本圖片都被歸一化爲一樣的尺寸大小(例如,20x20)。反例樣本能夠來自於任意的圖片,但這些圖片不能包含目標特徵。   

 正樣本:    

1.先準備正樣本圖片。

進入路徑tools\temp\positive\rawdata(個人路徑是F:\tools\temp\positive\rawdata,你按照你本身的路徑對應的改過來就好了),而後在裏面放入含有正樣本的圖片。固然了,正樣本數目要要足夠大,通常要是1000以上吧。注意,圖片要用BMP格式,若是你手頭上的圖片不是BMP格式的話,只須要用圖片處理軟件轉一下就好了。以下圖所示:

2.截圖目標區域。

正樣本圖片有了,而後雙擊F:\tools\temp\positive下的objectmarker.exe,開始截圖目標區域,有readme文件已經說明了,也就是說,每次截圖完要按一次空格鍵保存區域,多目標的圖片能夠接着繼續截圖,按下回車鍵能夠跳到寫一張圖片:

The following keys are used:

<Enter> save added rectangles and show next image

<ESC> exit program

<Space> add rectangle to current imageany other key clears rectangle drawing only

這個過程要持續下去不能中斷,否則的話就沒法產生相應的文件了,因此在樣本太多的狀況下,能夠先分組,大約100張圖片放進去rawdata中去,這樣子若是有什麼意外的話,損失也就100張圖的時間而已。只須要最後把幾個文件合成一個大文件,效果就同樣了。最後能夠在F:\tools\temp\positive下生成info.txt文件。

例子:

rawdata/11022923.BMP 1 11 5 100 78    

這裏,rawdata/11022923.BMP表示文件的相對路徑; 

  1 表示有一個目標(若是圖片中有兩個目標的話,截兩次圖,這裏就是2了,以此類推;

  11 5 表示目標矩形框起點座標;

  100 78 表示目標矩形框的寬和高。

3.正樣本描述文件vec文件的建立。

    已經把目標的狀況記錄了放在txt文件裏,接下來就編輯F:\tools下的samples_creation.bat文件,由於正樣本數是8個(我這裏是8個),因此改爲createsamples.exe -info positive/info.txt -vec data/vector.vec -num 8 -w 24 -h 24這句話的-num 後面寫個8就好了,後面的-w 和 -h 說的是圖片resize成的大小,根據你的須要本身改。以後會在F:\tools\temp\data下面生成vector.vec文件,這個就是向量描述文件了。

到此,正樣本的操做已經完成了,不用打開vec文件,由於這個要專門的軟件才能夠打開的。  

負樣本:   

 1.準備負樣本圖片。

到F:\tools\temp\negative下,把負樣本圖片放進去。通常來講,負樣本要比正樣本數目多不少。爲何呢?由於負樣本表示的是隨機狀況,只要有大量隨機樣本的狀況下,才能夠充分表示與正樣本相反的狀況,大約2-5倍吧,也不能太多,否則的話花費的時間太長,分類效果可能反而很差,由於比例偏移太嚴重了

    

2.負樣本描述文件的生成。

打開F:\tools\temp\negative下的create_list.bat文件,能夠自動生成描述文件。若是沒有找到這個create_list.bat批出處理文件,就本身在這個目錄下新建一個,內容就一句話:dir /b *.BMP >infofile.txt,而後保存。

infofile.txt文件內容以下爲例(注意負樣本也是bmp文件):

172328267.BMP

172328277.BMP

172328457.BMP

172328467.BMP

172328747.BMP

172328957.BMP

172328967.BMP

172329137.BMP

172329147.BMP

172329347.BMP

172329517.BMP

.............

到此,負樣本的操做結束。   

二.進入訓練階段:

   打開F:\tools下的haarTraining.bat,開始訓練了(注意:下載到的訓練和測試工具裏haarTraining.bat文件內容不必定適合你的實際狀況,注意按照下面的參數說明修改參數,特別是 -npos 20 -nneg 40 -nstages 5!!)。該文件參數說明以下: 

-data data/cascade -vec data/vector.vec -bg negative/infofile.txt -npos 20 -nneg 40 -nstages 5 -mem 1000 -mode ALL -w 24 -h 24 -nonsym

-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,則一個簡單的stump classifier 被使用。若是是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 次方。

  

訓練過程會在F:\tools\temp\data\cascade中產生相應階段的文件。訓練時間和電腦配置和訓練數據的多少有關。若是在這個過程當中中斷了也不要緊,再次啓動訓練能夠接着訓練下去的。(ctrl+c能夠退出)。個人配置是CPU:i5-480M,內存2G,正樣本2500,負樣本4500,大概從下午4點到次日早上7點吧,生成18級。速度比其餘博客上寫的要快不少,有的網友居然有用了6天的,我就搞不懂了。。。可能數據是在太大了吧。若是發現訓練着程序再也不動了,那麼不到18級也能夠中止了。生成18級的階段性分類器文件以後,把\temp\data\cascade下的n(這裏n=18)個弱分類器文件夾拷貝到cascade2xml\data下,用F:\tools\cascade2xml下的convert.bat就能夠生成xml分類器文件了。默認在同級目錄下生成output.xml,固然了,你也能夠改~~

3、檢測 

  生成分類器以後,就能夠啓用F:\tools\test_recognition下的facedetect.exe文件了,至於文件路徑什麼的,本身結合實際修改一下,就是要把這個output.xml做爲分類器文件輸入就是了。  

 例如:start.bat中

facedetect.exe --cascade="dane.xml" 0  

 就是使用F:\tools\test_recognition下的dane.xml文件,媒體文件來源是攝像頭,你要用視頻,就改成相似於xxx.avi或者其餘路徑就好了。

其實這個facedetect.exe 是有源代碼的,你能夠本身去opencv 自帶的代碼裏面找,我這裏也貼出來了。

本博客涉及到的資源:

正樣本:http://download.csdn.net/detail/zhuangxiaobin/7326197

負樣本:http://download.csdn.net/detail/zhuangxiaobin/7326205

訓練和檢測工具:http://download.csdn.net/detail/zhuangxiaobin/7414793

分類器xml文件:http://download.csdn.net/detail/zhuangxiaobin/7553415

我在正樣本和訓練工具設置了下載積分是1,一方面是正樣本的製做是在太耗我時間了,另外一方面實在是由於我窮苦過久,對積分十分渴望。ps:請原諒個人庸俗,呵呵~

我把檢測視頻也共享出來了,http://pan.baidu.com/s/1i3ADest

若是以爲能夠的話,請在下面頂一下吧~~

除了本文提供的資源以外,再也不提供任何其餘相關資源,本身去找,沒必要私信我索要。

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. #include "cv.h"  
  2. #include "highgui.h"  
  3. #include <stdio.h>  
  4. #include <stdlib.h>  
  5. #include <string.h>  
  6. #include <assert.h>  
  7. #include <math.h>  
  8. #include <float.h>  
  9. #include <limits.h>  
  10. #include <time.h>  
  11. #include <ctype.h>  
  12. static CvMemStorage* storage = 0;  
  13. static CvHaarClassifierCascade* cascade = 0;  
  14. void detect_and_draw( IplImage* image );  
  15. const char* cascade_name =  
  16.     "haarcascade_frontalface_alt.xml";  
  17. int main( int argc, char** argv )  
  18. {  
  19.     CvCapture* capture = 0;  
  20.     IplImage *frame, *frame_copy = 0;  
  21.     int optlen = strlen("--cascade=");  
  22.     const char* input_name;  
  23.     if( argc > 1 && strncmp( argv[1], "--cascade=", optlen ) == 0 )  
  24.     {  
  25.         cascade_name = argv[1] + optlen;  
  26.         input_name = argc > 2 ? argv[2] : 0;  
  27.     }  
  28.     else  
  29.     {  
  30.         fprintf( stderr,  
  31.         "Usage: facedetect --cascade=\"<cascade_path>\" [filename|camera_index]\n" );  
  32.         return -1;  
  33.          
  34.     }  
  35.     cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );  
  36.     if( !cascade )  
  37.     {  
  38.         fprintf( stderr, "ERROR: Could not load classifier cascade\n" );  
  39.         return -1;  
  40.     }  
  41.     storage = cvCreateMemStorage(0);  
  42.     if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )  
  43.         capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );  
  44.     else  
  45.         capture = cvCaptureFromAVI( input_name );  
  46.     cvNamedWindow( "result", 1 );  
  47.     if( capture )  
  48.     {  
  49.         for(;;)  
  50.         {  
  51.             if( !cvGrabFrame( capture ))  
  52.                 break;  
  53.             frame = cvRetrieveFrame( capture );  
  54.             if( !frame )  
  55.                 break;  
  56.             if( !frame_copy )  
  57.                 frame_copy = cvCreateImage( cvSize(frame->width,frame->height),  
  58.                                             IPL_DEPTH_8U, frame->nChannels );  
  59.             if( frame->origin == IPL_ORIGIN_TL )  
  60.                 cvCopy( frame, frame_copy, 0 );  
  61.             else  
  62.                 cvFlip( frame, frame_copy, 0 );  
  63.             detect_and_draw( frame_copy );  
  64.             if( cvWaitKey( 10 ) >= 0 )  
  65.                 break;  
  66.         }  
  67.         cvReleaseImage( &frame_copy );  
  68.         cvReleaseCapture( &capture );  
  69.     }  
  70.     else  
  71.     {  
  72.         const char* filename = input_name ? input_name : (char*)"lena.jpg";  
  73.         IplImage* image = cvLoadImage( filename, 1 );  
  74.         if( image )  
  75.         {  
  76.             detect_and_draw( image );  
  77.             cvWaitKey(0);  
  78.             cvReleaseImage( &image );  
  79.         }  
  80.         else  
  81.         {  
  82.              
  83.             FILE* f = fopen( filename, "rt" );  
  84.             if( f )  
  85.             {  
  86.                 char buf[1000+1];  
  87.                 while( fgets( buf, 1000, f ) )  
  88.                 {  
  89.                     int len = (int)strlen(buf);  
  90.                     while( len > 0 && isspace(buf[len-1]) )  
  91.                         len--;  
  92.                     buf[len] = '\0';  
  93.                     image = cvLoadImage( buf, 1 );  
  94.                     if( image )  
  95.                     {  
  96.                         detect_and_draw( image );  
  97.                         cvWaitKey(0);  
  98.                         cvReleaseImage( &image );  
  99.                     }  
  100.                 }  
  101.                 fclose(f);  
  102.             }  
  103.         }  
  104.     }  
  105.     cvDestroyWindow("result");  
  106.     return 0;  
  107. }  
  108. void detect_and_draw( IplImage* img )  
  109. {  
  110.     int scale = 1.3;  
  111.     IplImage* temp = cvCreateImage( cvSize(img->width/scale,img->height/scale), 8, 3 );  
  112.     CvPoint pt1, pt2;  
  113.     int i;  
  114.   
  115.     cvClearMemStorage( storage );  
  116.     if( cascade )  
  117.     {  
  118.         CvSeq* faces = cvHaarDetectObjects( img, cascade, storage,  
  119.                                             1.1, 3, CV_HAAR_DO_CANNY_PRUNING,  
  120.                                             cvSize(20, 20) );  
  121.         for( i = 0; i < (faces ? faces->total : 0); i++ )  
  122.         {  
  123.             CvRect* r = (CvRect*)cvGetSeqElem( faces, i );  
  124.             pt1.x = r->x*scale;  
  125.             pt2.x = (r->x+r->width)*scale;  
  126.             pt1.y = r->y*scale;  
  127.             pt2.y = (r->y+r->height)*scale;  
  128.             cvRectangle( img, pt1, pt2, CV_RGB(255,0,0), 3, 8, 0 );  
  129.         }  
  130.     }  
  131.     cvShowImage( "result", img );  
  132.     cvReleaseImage( &temp );  
相關文章
相關標籤/搜索