天天看点

HOG Detector ~ Training OLTbinaries

http://lego.twgg.org/?p=852

最近糊里糊塗的完成了 HOG Detector 對於輪胎偵測的訓練(效果挺優 !!),

都要感謝此網站的達人:http://blog.baifaces.com/baifaces/blog/work/opencv-hog-peopledetector-trainning.html

在此也記錄一下,我實作時的疑難雜症吧!!

實作平台是:Ubuntu 11.04

釋出訓練程式的網站:http://pascal.inrialpes.fr/soft/olt/ (載點) (樣本檔)

樣本檔容量很大,如果只是要單純訓練自己的樣本的話,大可不用抓。

步驟紀錄如下:

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

[[email protected] HOG]$ wget http:

//pascal

.inrialpes.fr

/soft/olt/OLTbinaries

.zip

[[email protected] HOG]$ unzip OLTbinaries.zip

[[email protected] HOG]$

cd

OLTbinaries

//

建立樣本資料夾 train 與

test

[[email protected] OLTbinaries]$

mkdir

train

test

//

把你的正樣本 copy 到 train 與

test

目錄中 (pos為你放正樣本圖片的資料夾)

[[email protected] OLTbinaries]$

cp

-r pos train/

[[email protected] OLTbinaries]$

cp

-r pos

test

/

//

把你的負樣本 copy 到 train 與

test

目錄中 (neg為你放負樣本圖片的資料夾)

[[email protected] OLTbinaries]$

cp

-r neg train/

[[email protected] OLTbinaries]$

cp

-r neg

test

/

//

建立正負樣本的 list

[[email protected] OLTbinaries]$

find

train

/pos

> train

/pos

.lst

[[email protected] OLTbinaries]$

find

test

/pos

>

test

/pos

.lst

[[email protected] OLTbinaries]$

find

train

/neg

> train

/neg

.lst

[[email protected] OLTbinaries]$

find

test

/neg

>

test

/neg

.lst

//

做完上述指令後,需要把上面的每一個 lst 檔的第一行 刪掉

//

修改 runall.sh 把其中的 WIDTH 與 HEIGHT 改成你自己的正樣本大小

[[email protected] OLTbinaries]$

vi

runall.sh

WIDTH=64;

export

WIDTH

HEIGHT=128;

export

HEIGHT

//

接下來就開始訓練了 !!! (我訓練的正樣本有 1133 張 size 50 x 50,負樣本有 680 張 size 512x384)

//

跟 AdaBoost 比起來,HOG Detector 的訓練時間算是很快!!

[[email protected] OLTbinaries]$ sh runall.sh

//

等待 runall.sh 跑完後,便可看到 OLTbinaries

/HOG

目錄下,產生了一個 model

file

//

此即為我們訓練好的檔案。

[[email protected] OLTbinaries]$

ls

HOG

/model_4BiSVMLight

.alt

HOG

/model_4BiSVMLight

.alt

以上為訓練過程,以下備註一下注意事項:

1. 訓練的正、負圖片可以是 png 或 jpg ( 我用 bmp 時,會出錯 ),還有就是副檔名要小寫。

2. 若要改變訓練完的 model 檔名稱與位置,可在 runall.sh 中修改。

做完訓練,接下來就是測試訓練檔好不好用啦!!

在此它有提供 runonimage.sh 讓我們測試,用法如下:

## 使用前記得先修改 runonimage.sh 內的正樣本圖片長、寬(與你訓練的正樣本長、寬要一樣),不然會出錯。

WIDTH=64; export WIDTH

HEIGHT=128; export HEIGHT

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18

# runonimage.sh {image name/image directory/list file} {out text file} {out image file/out image dir}

//

總共有三個參數

參數1: 可直接指定預測試的圖片檔名 (ex: photo.jpg ),或者是一個存放圖片清單的檔案

( ex: 存放所有你要測試圖片清單的檔案 image.lst 內容如:

test

/photo1

.jpg )

參數2: 測試過程中,可能會有一些測試結果的資訊, 這些資訊會存入該參數指定的檔案

參數3: 測試完畢後,該程式會將偵測物件的結果資訊,畫在圖片上,因此該參數便是指定這張被繪製偵測結果資訊的圖片的位置,

如果你指定的是圖片檔名,則會以該檔名進行儲存;

如果你指定的是一個目錄,則會以原始測試的檔名,儲存在你指定的目錄中。

//

實際指令下法

# 1 測試單張圖片

[[email protected] OLTbinaries]$ sh runonimage.sh photo.jpg result.txt result.jpg

# 2 測試大量圖片

[[email protected] OLTbinaries]$ sh runonimage.sh image.lst result.txt result_folder/

測試的圖片,還是盡量使用 jpg 或 png 且輸出的附檔名一定要是小寫,不然有時候跑起來程式會一直出錯,挺麻煩的。

在此SHOW三張偵測結果圖吧 (效果不賴):

HOG Detector ~ Training OLTbinaries
HOG Detector ~ Training OLTbinaries
HOG Detector ~ Training OLTbinaries

當然 ~ 有時候難免有誤判 。

HOG Detector ~ Training OLTbinaries

以後有空再把它整進 Android 手機中試看看好了 !!! 先

为了验证这一想法的正确性和可行性,笔者做了些实验,在Ubuntu10.4 g++4.4.5环境中,步骤如下:

  1. 下载release版的程序:OLTbinaries.zip
  2. 下载样本:INRIAPerson.tar
  3. 在目录OLTbinaries/下建立两个文件夹test, train. 将INRIAperson/Test/neg拷贝到test/下,INRIAperson/Train/neg拷贝到train/下;将INRIAperson/test_64x128_H96拷贝到test/下重命名为pos,将INRIAperson/train_64x128_H96拷贝到train/下重命名为pos;
  4. 将test/neg , test/pos各自文件夹中的所有图片文件名分别输出到neg.list, pos.list, 并放置在test/下; 同样地操作在train/。<pre class="brush: shell; gutter: true">[email protected]:~/Projects/opencv/OLTbinaries/test$ ls ./neg &gt; neg.list [email protected]:~/Projects/opencv/OLTbinaries/test$ ls ./pos &gt; pos.list
  5. 到这里,样本数据便准备好了,那么,只要修改OLTbinaries/runall.sh相关参数然后这些此脚本,一小时左右的时间,便会在OLTbinaries/HOG/下产生一个model_4BiSVMLight.alt文件,你的模型数据便保存在这里面。到这里,你便成功trainning了一个model。

注意事项:

  • runall.sh中第5行,按你的正负样本数目修改:
    1 HardOption=" --poscases 2416 --negcases 1218 "
  • runall.sh中第21行,按你的样本文件夹所在(InDir)及输出文件所在(OutDir)修改:
    1 2 3 4 OutDir=./HOG InDir=./ OutFile=$OutDir/record CMDLINE=$OutDir/record
  • trainning过程中会产生两个G左右的临时文件在OutDir(=./HOG)中,所以要确保硬盘空间足够,结束时删除,只留model_4BiSVMLight.alt。
  • 整个trainning过程分4步,有4条屏幕输出信息,最可能出现的错误是样本文件路径不对,可在pos.list neg.list 中用图像文件的绝对路径。
    1 2 3 4 First iteration complete Hard examples created Doing second learning Second iteration complete
  • 如果你用的是自己的样本,注意修改其他参数(待究),如正样本的大小:
    1 2 WIDTH=64; export WIDTH HEIGHT=128; export HEIGHT

有了模型,怎么去做目标检测呢?你可以做以下的试验:

  1. 使用bin在OLTbinaries/bin/中classify_rhog: classify_rhog [待检测图片] [目标位置数据结果保存的文本文件] [模型文件] -i [位置画在图像文件][email protected]:~/Projects/opencv/OLTbinaries/bin$ ./classify_rhog  person-1.jpg  result.txt model_4BiSVMLight.alt -i result.jpg

    结果:

    HOG Detector ~ Training OLTbinaries
  2. 使用lib在OLTbinaries/lib/中:
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 #include <cv.h> #include <highgui.h> #include <string> #include <iostream> #include <algorithm> #include <iterator> #include <X11/Xlib.h> #include <Imlib2.h> #include <lear/interface/windetect.h>// change this path as appropriate. using namespace std; std::list<DetectedRegion> detector(char* imgf, WinDetectClassify windetect, LinearClassify* classifier) {     std::list<DetectedRegion> detections;     // read image     Imlib_Image image = imlib_load_image(imgf);     // if the load was successful     if (image)     {// set the image we loaded as the current context image to work on         imlib_context_set_image(image);     } else {         //std::cerr << "Unable to read image: " << argv[1] << std::endl;         return detections;     }     int width  = imlib_image_get_width(),         height = imlib_image_get_height();     typedef unsigned char uchar;     DATA32* data = imlib_image_get_data_for_reading_only();     uchar* imagedata = new uchar[3*width*height*sizeof(uchar)];     for (int j= 0; j< height; ++j)     for (int i= 0; i< width; ++i) {         uchar* pixel = imagedata+(i+j*width)*3;         int argb = data[i+j*width];         pixel[0] = static_cast<uchar>((argb & 0x00FF0000)>>16);         pixel[1] = static_cast<uchar>((argb & 0x0000FF00)>> 8);         pixel[2] = static_cast<uchar>((argb & 0x000000FF)    );     }     imlib_free_image();     // now get detections     windetect.test(*classifier, detections, imagedata, width, height);     delete[] imagedata;     return detections; } int main(int argc, char** argv) {     if (argc != 4) {         std::cout << "Error" << std::endl;         return 0;     }     char modelpath[256];     strcpy(modelpath,argv[2]);     string model_file(modelpath) ;     // initialize the person detector. All default parameters are set for person detector.     WinDetectClassify windetect;// use default person detector.     RHOGDenseParam desc;     LinearClassify* classifier = NULL;// initialize it to 64x128 person detector.     classifier = new LinearClassify(model_file, 0);     windetect.init(&desc); // initialize the descriptor computation     std::list<DetectedRegion> detections;     detections = detector(argv[1], windetect, classifier);     //draw region in image     IplImage* img = cvLoadImage(argv[1],1);     for(list<DetectedRegion>::iterator itor=detections.begin();itor!=detections.end();++itor)     {          cvRectangle(img,cvPoint(itor->x,itor->y),cvPoint(itor->x+itor->width,itor->y+itor->height),cvScalar(0,0,255),2);     }     cvSaveImage(argv[3],img);     cvReleaseImage(&img);     //print detections     std::copy(detections.begin(), detections.end(), std::ostream_iterator<DetectedRegion>(std::cout, "\n"));     return 0; }
    编译:
    1 g++ `pkg-config --cflags --libs opencv` -O3 -o lib-detector lib-detector.cpp   -I.  -I/usr/include -L. -lcmdline -lcvip -lclassifier -llearutil -lboost_filesystem-gcc  -lblitz -L/usr/lib -lImlib2 -lfreetype -lz -L/usr/X11R6/lib -lX11 -lXext -ldl -lm
    结果:
    1 2 3 4 [email protected]:~/Projects/opencv/OLTbinaries/lib$ ./lib-detector person-1.jpg   model_4BiSVMLight.alt  result.jpg    298    215    145    290    2.2674 1.10256009e-01     13      9    237    475   3.71704 1.31164089e-01    234     -7    230    460   3.59693 1.35627717e-01
  3. 使用源码在learcode/app/中classify_rhog.cpp:配置及使用见learcode/README

继续阅读