最近尝试了一下用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 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);
vectorpos_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));
vectordescriptor;
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(i);
int *pl = sample_label_mat.ptr(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));
vectordescriptor;
hog->compute(train_data, descriptor, Size(8, 8));
float *pf = sample_feature_mat.ptr(i + pos_sample_num);
int *pl = sample_label_mat.ptr(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 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%
分类结果还行,增加训练数据还能达到更高的准确率
网上也很多例程,我就不详细说明了