利用SVM进行图像目标检测和分类

#include <iostream>    
#include <opencv2/opencv.hpp>  
#include <opencv2/core/core.hpp>    
#include <opencv2/highgui/highgui.hpp>   
#include <opencv2/imgproc/imgproc.hpp>   
#include<opencv2/ml/ml.hpp>
using namespace cv;
using namespace std;


Mat img, image;
Mat targetData, backData;
bool flag = true;
string wdname = "image";

void on_mouse(int event, int x, int y, int flags, void* ustc); //鼠标取样本点
void getTrainData(Mat &train_data, Mat &train_label);  //生成训练数据 
void svm(); //svm分类


int main(int argc, char** argv)
{
	string path = "1.png";
	img = imread(path);
	img.copyTo(image);
	if (img.empty())
	{
		cout << "Image load error";
		return 0;
	}
	namedWindow(wdname);
	setMouseCallback(wdname, on_mouse, 0);

	for (;;)
	{
		imshow("image", img);

		int c = waitKey(0);
		if ((c & 255) == 27)
		{
			cout << "Exiting ...\n";
			break;
		}
		if ((char)c == 'c')
		{
			flag = false;
		}
		if ((char)c == 'q')
		{
			destroyAllWindows();
			break;
		}
	}
	svm();
	return 0;
}

//鼠标在图像上取样本点,按q键退出
void on_mouse(int event, int x, int y, int flags, void* ustc)
{
	if (event == CV_EVENT_LBUTTONDOWN)
	{
		Point pt = Point(x, y);
		Vec3b point = img.at<Vec3b>(y, x);  //取出该坐标处的像素值,注意x,y的顺序
		Mat tmp = (Mat_<float>(1, 3) << point[0], point[1], point[2]);
		if (flag)
		{
			targetData.push_back(tmp); //加入正样本矩阵
			circle(img, pt, 2, Scalar(0, 255, 255), -1, 8); //画出点击的点 

		}

		else
		{
			backData.push_back(tmp); //加入负样本矩阵
			circle(img, pt, 2, Scalar(255, 0, 0), -1, 8);

		}
		imshow(wdname, img);
	}
}

void getTrainData(Mat &train_data, Mat &train_label)
{
	int m = targetData.rows;
	int n = backData.rows;
	cout << "正样本数::" << m << endl;
	cout << "负样本数:" << n << endl;
	vconcat(targetData, backData, train_data); //合并所有的样本点,作为训练数据
	train_label = Mat(m + n, 1, CV_32S, Scalar::all(1)); //初始化标注
	for (int i = m; i < m + n; i++)
		train_label.at<int>(i, 0) = -1;
}

void svm()
{
	Mat train_data, train_label;
	getTrainData(train_data, train_label); //获取鼠标选择的样本训练数据

	
	CvSVMParams params;
	params.svm_type = CvSVM::C_SVC;
	params.kernel_type = CvSVM::LINEAR;
	params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);

	// 对SVM进行训练
	CvSVM SVM;
	SVM.train(train_data, train_label, Mat(), Mat(), params);

	Vec3b color(0, 0, 0);
	// Show the decision regions given by the SVM
	for (int i = 0; i < image.rows; ++i)
		for (int j = 0; j < image.cols; ++j)
		{
		Vec3b point = img.at<Vec3b>(i, j);  //取出该坐标处的像素值
		Mat sampleMat = (Mat_<float>(1, 3) << point[0], point[1], point[2]);
		float response = SVM.predict(sampleMat);  //进行预测,返回1或-1,返回类型为float
		if ((int)response != 1)
			image.at<Vec3b>(i, j) = color;  //将背景设置为黑色
		}

	imshow("SVM Simple Example", image);
	waitKey(0);
}


代码如上:

1.首先输入图像,调用setMouseCallback函数进行鼠标取点

2.用鼠标在图像上点击,取出当前点的红绿蓝像素值进行训练。先选择任意个目标样本,然后按"c“键后选择任意个背景样本。样本数可以自己随意决定。样本选择完后,按”q"键完成样本选择。

3.将正负样本矩阵,用vconcat合并成一个矩阵,用作训练分类器,并对相应的样本进行标注。最后将识别出的目标保留,将背景部分调成黑色。

原图:


效果图:


  • 3
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值