opencv进阶-自定义对象检测
Posted 殇堼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opencv进阶-自定义对象检测相关的知识,希望对你有一定的参考价值。
HOG+SVM
缺点:计算量大,实时性差
HOG的详细介绍参考:
梯度直方图的学习:
归一化的学习:
SVM的详细介绍参考:SVM学习(一):SVM概念
1、pos文件夹 (正样本)
2、neg文件夹 (负样本 训练时所需文件)
3、xml (分类器保存的位置)
4、pos.txt (正样本图片路径和图片大小说明)
5、neg.txt (负样本图片路径说明 训练时所需文件)
6、pos.vec (pos.txt->pos.vec 训练时所需文件)
7、create_sample.bat (pos.txt->pos.vec的命令)
8、treain.bat (训练的命令)
全部代码
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
using namespace cv::ml;
string positive_dir = "";
string negative_dir = "";
void get_hog_descriptor(Mat &image, vector<float>&desc);
void generate_dataset(Mat &trainData, Mat &labels);
void svm_train(Mat &trainData, Mat&labels);
int main() {
//read data and generate dataset
Mat trainData = Mat::zeros(Size(3780, 26), CV_32FC1);
Mat labels = Mat::zeros(Size(1, 26), CV_32FC1);
generate_dataset(trainData, labels);
//svm train and save model;
svm_train(trainData, labels);
//load model
Ptr<SVM>svm = SVM::load("D:/images/hog_.xml");
//detect custom object
Mat test=imread("D:/images/");
resize(test, test, Size(0, 0), 0.2, 0.2);
imshow("input image", test);
Rect winrect;
winrect.width = 64;
winrect.height = 128;
int sum_x = 0;
int sum_y = 0;
int count = 0;
//开窗检测
for (int row = 64; row < test.rows-64; row+=4) {
for (int col = 32; col < test.cols - 32; col+=4) {
winrect.x = col - 32;
winrect.y = row - 64;
vector<float>fv;
get_hog_descriptor(test(winrect), fv);
Mat one_row = Mat::zeros(Size(fv.size(), 1), CV_32FC1);
for (int i = 0; i < fv.size(); i++) {
one_row.at<float>(0, 1) = fv[i];
}
float result = svm->predict(one_row);
if (result > 0) {
rectangle(test, winrect, Scalar(0, 0, 255), 1, 8, 0);
count += 1;
sum_x += winrect.x;
sum_y += winrect.y;
}
}
}
//显示box
winrect.x = sum_x / count;
winrect.y = sum_y / count;
rectangle(test, winrect, Scalar(0, 255, 0), 2, 8, 0);
imshow("object_test", test);
waitKey(0);
return 0;
}
void get_hog_descriptor(Mat &image, vector<float>&desc) {//hog描述子的提取
HOGDescriptor hog;
int h = image.rows;
int w = image.cols;
float rate = 64 / w;
Mat img, gray;
resize(image, img, Size(64, int(rate*h)));
cvtColor(img, gray, COLOR_BGR2GRAY);
Mat result = Mat::zeros(Size(64, 128), CV_8UC1);
result = Scalar(127);
Rect roi;
roi.x = 0;
roi.y = (128 - gray.rows) / 2;
roi.width = 64;
roi.height = gray.rows;
gray.copyTo(result(roi));
hog.compute(result, desc, Size(8, 8), Size(0, 0));
printf("desc len:%d\\n", desc.size());
}
void generate_dataset(Mat &trainData, Mat &labels) {//定义正负样本
vector<string>images;
glob(positive_dir, images);
int pos_num = images.size();
for(int i = 0; i < images.size(); i++) {
Mat image = imread(images[i].c_str());
vector<float>fv;
get_hog_descriptor(image, fv);
for (int j = 0; j < fv.size(); j++) {
trainData.at<float>(i, j) = fv[j];
}
labels.at<int>(i,0)=1 ;
}
//定义负样本
images.clear();
glob(negative_dir,images);
for(int i = 0; i < images.size(); i++) {
Mat image = imread(images[i].c_str());
vector<float>fv;
get_hog_descriptor(image, fv);
for (int j = 0; j < fv.size(); j++) {
trainData.at<float>(i + pos_num, j) = fv[j];
}
labels.at<int>(i, 0) = -1;
}
}
void svm_train(Mat &trainData, Mat&labels) {
printf("\\n start svm traing...");
Ptr<SVM>svm = SVM::create();
svm->setC(2.67);
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);
svm->setGamma(5.383);
svm->train(trainData, ROW_SAMPLE, labels);
clog << "...[Done]" << endl;
printf(" train end... \\n");
//SVM训练和保存模型,save xml;
svm->save("");
}
以上是关于opencv进阶-自定义对象检测的主要内容,如果未能解决你的问题,请参考以下文章
opencv进阶-基于coco数据集训练好的模型,修改类别显示代码,实现自定义检测物体