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数据集训练好的模型,修改类别显示代码,实现自定义检测物体

opencv进阶-基于coco数据集训练好的模型,修改类别显示代码,实现自定义检测物体

opencv进阶-检测使用鼠标框选的自定义区域

opencv进阶-Faster RCNN对象检测模型使用

opencv进阶-YOLO对象检测的代码解读

opencv进阶-SSD模型实时对象检测(摄像头)