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 | |
以上為訓練過程,以下備註一下注意事項:
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 | |
測試的圖片,還是盡量使用 jpg 或 png 且輸出的附檔名一定要是小寫,不然有時候跑起來程式會一直出錯,挺麻煩的。
在此SHOW三張偵測結果圖吧 (效果不賴):
當然 ~ 有時候難免有誤判 。
以後有空再把它整進 Android 手機中試看看好了 !!! 先
为了验证这一想法的正确性和可行性,笔者做了些实验,在Ubuntu10.4 g++4.4.5环境中,步骤如下:
- 下载release版的程序:OLTbinaries.zip
- 下载样本:INRIAPerson.tar
- 在目录OLTbinaries/下建立两个文件夹test, train. 将INRIAperson/Test/neg拷贝到test/下,INRIAperson/Train/neg拷贝到train/下;将INRIAperson/test_64x128_H96拷贝到test/下重命名为pos,将INRIAperson/train_64x128_H96拷贝到train/下重命名为pos;
- 将test/neg , test/pos各自文件夹中的所有图片文件名分别输出到neg.list, pos.list, 并放置在test/下; 同样地操作在train/。<pre class="brush: shell; gutter: true">[email protected]:~/Projects/opencv/OLTbinaries/test$ ls ./neg > neg.list [email protected]:~/Projects/opencv/OLTbinaries/test$ ls ./pos > pos.list
- 到这里,样本数据便准备好了,那么,只要修改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
有了模型,怎么去做目标检测呢?你可以做以下的试验:
-
使用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
结果:
- 使用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 - 使用源码在learcode/app/中classify_rhog.cpp:配置及使用见learcode/README