1. 程式人生 > >opencv +Hog + SVM 車輛檢測

opencv +Hog + SVM 車輛檢測

最近嘗試了一下用opencv做了一下車輛檢測
其中hog特徵使用opencv自帶函式庫進行提取描述如下:

HOGDescriptor *hog = new HOGDescriptor(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9);

上述引數中第一個size代表讀入訓練資料中影象的大小
第二個為滑動視窗大小
第三個滑動步長
第四個cell的大小
然後就是SVM的使用了

    Ptr < SVM > svm = SVM::create(); //建立物件
	svm->setType(SVM::C_SVC); 
	svm->setKernel(SVM::LINEAR); //線性核
	//匯入特徵矩陣  每一行代表一個特徵向量  最後為特徵標籤
	Ptr<TrainData> tData = TrainData::create(sample_feature_mat, ROW_SAMPLE,sample_label_mat);
	//自動設定相應引數並訓練
	svm->trainAuto(tData);

再看看為什麼hog特徵能較好的對車輛分類
下圖顯示了我對100個包含車輛的樣本(影象上部)與200個不包含車輛的樣本(影象下部)進行視覺化,顯然包含車輛的特徵向量與不包含車輛的特徵向量有明顯區別
所以hog特徵能較強的描述目標物體的形狀資訊
而一般影象中物體特徵的表達通常用形狀、紋理或者顏色等特徵來描述
一般人體或車輛等能夠被形狀較強的表徵,而hog特徵正好適合來表徵物體的形狀資訊,所以一般用hog特徵來做行人或者車輛檢測等等…
在這裡插入圖片描述
完整程式碼如下:

   //我用的是opencv3.4 HOG與SVM的使用與2.X版本的有些區別
    string pos_path = "正樣本路徑";
	string neg_path = "負樣本路徑";
	Mat sample_feature_mat,sample_label_mat;
	ifstream input_pos_sample(pos_path);
	ifstream input_neg_sample(neg_path);
	vector<string>pos_sample_path,neg_sample_path,feature_dim;
	string str;
	int pos_sample_num,neg_sample_num ;
	while (getline(input_pos_sample, str))  pos_sample_path.push_back(str);
	while (getline(input_neg_sample, str))  neg_sample_path.push_back(str);
	pos_sample_num = pos_sample_path.size();
	neg_sample_num = neg_sample_path.size();
	input_pos_sample.close();
	input_neg_sample.close();
	HOGDescriptor *hog = new HOGDescriptor(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 9);
	//正樣本hog特徵提取
	for (int i = 0; i < pos_sample_num; ++i) {
		Mat input_img = imread(pos_sample_path[i],0);
		Mat train_data(64, 64, CV_32FC1);
		resize(input_img, train_data, Size(64, 64));
		vector<float>descriptor;
		hog->compute(train_data, descriptor, Size(8, 8));
		if (i == 0) {
			feature_dim = descriptor.size();
			sample_feature_mat = Mat::zeros(pos_sample_num + neg_sample_num, feature_dim, CV_32FC1);
			sample_label_mat = Mat::zeros(pos_sample_num + neg_sample_num, 1, CV_32SC1);
		}
		float *pf = sample_feature_mat.ptr<float>(i);
		int *pl = sample_label_mat.ptr<int>(i);
		for (int j = 0; j < feature_dim; ++j) {
			*pf++ = descriptor[j];
		}
		*pl++ = 1;
	}
	//負樣本hog特徵提取
	for (int i = 0; i < neg_sample_num; ++i) {
		Mat input_img = imread(neg_sample_path[i],0);
		Mat train_data(64, 64, CV_32FC1);
		resize(input_img, train_data, Size(64, 64));
		vector<float>descriptor;
		hog->compute(train_data, descriptor, Size(8, 8));
		float *pf = sample_feature_mat.ptr<float>(i + pos_sample_num);
		int *pl = sample_label_mat.ptr<int>(i + pos_sample_num);
		for (int j = 0; j < feature_dim; ++j) {
			*pf++ = descriptor[j];
		}
		*pl++ = -1;
	}
	//訓練資料
    Ptr < SVM > svm = SVM::create();
	svm->setType(SVM::C_SVC);
	svm->setKernel(SVM::LINEAR);
	Ptr<TrainData> tData = TrainData::create(sample_feature_mat, ROW_SAMPLE,sample_label_mat);
	cout << "train begin" << endl;
	svm->trainAuto(tData);
	svm->save("D:\\traindata\\SVM_Model.xml"); //訓練結果儲存檔案
	cout << "train done" << endl;

我用100個正樣本200個負樣本訓練車輛檢測
結果對於KITTI的車輛資料分類正確率大約90%
分類結果還行,增加訓練資料還能達到更高的準確率
網上也很多例程,我就不詳細說明了