1. 程式人生 > >opencv_haartraining.exe 訓練資料集自己經歷過的坑

opencv_haartraining.exe 訓練資料集自己經歷過的坑

1、opencv_haartraining.exe 在新版本里面沒有,之前在openv3.3.1 和 3.1.0 中都沒找打,看網上用的是2.4.9 ,然後才用 opencv249完成。

2、將圖片名稱輸入到 txt 檔案,最開始直接進入樣本圖片的資料夾,直接 dir /b > pos.txt ,這樣 pos.txt 檔名也會刷到該 txt 檔案中,而且在執行 opencv_haartraining.exe 過程中,負樣本的 txt 檔案必須和 opencv_haartraining.exe 在同一路徑下,使用

dir /b/s/p/w *.jpg > 路徑.txt,這樣對於替換 txt 裡面的內容更方便。

3、沒做正樣本資料歸一化,然後就會在某個地方一直迴圈下去,像如下圖這組資料,第一項 n 會一直增加,但是後面的值,一直不會被改變。

對於這個問題,在做了歸一化,和正樣本大小歸一化後,解決。

以下程式碼是對正樣本集做歸一化大小和灰度圖處理,然後儲存為新圖片:

#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/ml/ml.hpp"

#include <iostream>
#include <stdio.h>
#include <direct.h>
#include <fstream> 

using namespace std;
using namespace cv;

typedef enum{
	NEG = 0,
	POS,
}TYPE;

int main(int argc, char **argv)
{
	Mat image, ori;
	Mat	smallImg(20, 20, CV_8UC1);//將圖片縮小,加快檢測速度
	char *name = NULL;
	char *grayname = NULL;
	int insert = 0;
	int nameindex = 0;
	TYPE type;
	
	if (atoi(argv[1]) == 1)
	{
		type = POS;
	}
	else if (atoi(argv[1]) == 0)
	{
		type = NEG;
	}
	else
	{
		cout << "input type err, please input a num: 0 or 1..." << endl;
		int num;
		scanf("%d", &num);
		type = (TYPE)num;
	}
	grayname = (char *)malloc(20);
	if (grayname == NULL)
	{
		cout << "malloc grayname fail! " << endl;
		return -1;
	}
	
	name = (char *)malloc(20);
	if (name == NULL)
	{
		cout << "malloc name fail! " << endl;
		return -1;
	}

	cout << argv[1] << endl;
	char *txt;
	if (type == POS)
		txt = "positive\\pos.txt";
	else
		txt = "negative\\neg.txt";

	ifstream file(txt, ios::in | ios::binary | ios::ate);
	long size = file.tellg();
	cout << "size = " << size << endl;
	file.seekg(0, ios::beg);

	while (1)
	{
		file.read((name + insert), 1);
		//cout << name[insert] << endl;
		if (name[insert] == NULL)
			break;
		else if (insert > 0 && name[insert] == '\n')
		{
			memset(name+insert-1, NULL, 2);
			
			cout << "name = " << name << endl;
			image = imread(name, 1);
			if (!image.empty())//讀取圖片資料不能為空
			{
				if (type == POS)
				{
					sprintf(grayname, "GrayPos\\grayimg_%d.jpg", nameindex);
				}
				else
				{
					sprintf(grayname, "GrayNeg\\grayimg_%d.jpg", nameindex);
				}
				cout << grayname << endl;
				
				cvtColor(image, ori, COLOR_BGR2GRAY);

				cvtColor(image, ori, CV_BGR2GRAY);//因為用的是類haar特徵,所以都是基於灰度影象的,這裡要轉換成灰度影象
				resize(ori, smallImg, smallImg.size(), 0, 0, INTER_LINEAR);//將尺寸縮小到1/scale,用線性插值
				equalizeHist(smallImg, smallImg);//直方圖均衡
				imwrite(grayname, smallImg);
				nameindex++;
				//cv::destroyWindow("result");
			}
			memset(name, 0, 20);
			insert = 0;
			continue;
		}
		insert++;
	}

	file.close();
	free(name);
	free(grayname);
	cout << "Done,please input a key to exit..." << endl;
	getchar();
	return 0;
}
訓練命令
dir /b/s/p/w *.jpg > ..\neg.txt opencv_createsamples -vec pos.vec -info pos.txt -bg neg.txt -w 20 -h 20 opencv_haartraining.exe -data data\data -vec pos.vec -bg neg.txt -nstages 20 -nsplits 1 -npos 400 -nneg 1200 -mode all -w 20 -h 20