OpenCV:SVM目标分类简单示例

1. SVM:support vector machine支持向量机

2. 头文件:#inlcude “opencv/ml.hpp”

具体用法,见opencv官方注释

3. svm可用于目标分类,简单实例如下:

目的:去掉图中背景,提取蔬菜区域。

#include <iostream>
#include <opencv2/opencv.hpp>
#pragma comment(lib,"opencv_world341.lib")

using namespace cv;
using namespace std;
using namespace cv::ml;

//正负样本转换标志
//当为true时,标注正样本点
//当为false时,标注负样本点
bool flag = true;

string wdname = "image";
Mat img, image;
Mat targetData, backData;
//鼠标左键标记样本点
//按c键切换正负样本,按esc键生成训练样本数据,按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);  //取出该坐标处的像素值
		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;
}




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

	// 设置参数
	Ptr<SVM> svm = SVM::create();
	svm->setType(SVM::C_SVC);
	svm->setKernel(SVM::LINEAR);

	//训练分类器
	Ptr<TrainData> tData = TrainData::create(train_data, ROW_SAMPLE, train_label);
	svm->train(tData);

	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);
}


int main()
{
	img = imread("C:\\Users\\Administrator\\Desktop\\peppers.png");
	img.copyTo(image);
	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;
}

步骤:

s1. 先点击鼠标左键标注正样本数据;

s2. 按c键切换,标注负样本数据;

s3. 按esc键,进行分类;

 

4. svm的使用方法

4.1 载入训练数据,生成训练模型

4.2 设置分类参数,生成分类器,传入测试集,进行预测

4.3 示例如下:

#include <opencv2/opencv.hpp>
#include <iostream>
#pragma comment(lib,"opencv_world341.lib")
using namespace cv;
using namespace cv::ml;

int main()
{
	int width = 512, height = 512;
	Mat image = Mat::zeros(height, width, CV_8UC3);  

	//s1.载入训练数据,生成训练模型
	//训练数据
	float trainingData[10][2] = { { 501, 150 },{ 255, 10 },{ 501, 255 },{ 10, 501 },{ 25, 80 },
	{ 150, 300 },{ 77, 200 } ,{ 300, 300 } ,{ 45, 250 } ,{ 200, 200 } };
	Mat trainingDataMat(10, 2, CV_32FC1, trainingData);

	//训练标签,1 -1 两个标签
	int labels[10] = { 1, -1, 1, 1, -1, 1, -1, 1, -1, -1 };
	Mat labelsMat(10, 1, CV_32SC1, labels);//10行1列
	//设置训练数据 
	Ptr<TrainData> tData = TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);

	//显示训练数据
	int thickness = -1;
	int lineType = 8;
	Scalar c1 = Scalar::all(0); //标记为1的显示成黑点
	Scalar c2 = Scalar::all(255); //标记成-1的显示成白点
	for (int i = 0; i < labelsMat.rows; i++)
	{
		const float* v = trainingDataMat.ptr<float>(i);
		Point pt = Point((int)v[0], (int)v[1]);
		if (labels[i] == 1)
			circle(image, pt, 5, Scalar(0,255,0), -1, 8);
		else
			circle(image, pt, 5, Scalar(255,0,0), -1, 8);
	}
	imshow("train data", image);
	waitKey(0);



	//s2. 生成分类器,设置分类参数,输入测试数据进行预测
	// 创建分类器并设置参数
	Ptr<SVM> model = SVM::create();
	model->setType(SVM::C_SVC);
	model->setKernel(SVM::LINEAR);  //核函数
	// 训练分类器
	model->train(tData);

	Vec3b green(0, 255, 0), blue(255, 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)
		{
			//测试数据,点位(x,y)
			Mat sampleMat = (Mat_<float>(1, 2) << j, i); 
			//进行预测,返回1或-1
			float response = model->predict(sampleMat);  
			if (response == 1)
				image.at<Vec3b>(i, j) = green;
			else if (response == -1)
				image.at<Vec3b>(i, j) = blue;
		}

	imshow("SVM test", image);
	waitKey(0);

}

 

参考文章

1. https://www.cnblogs.com/denny402/p/5020551.html

2. https://www.cnblogs.com/denny402/p/5019233.html

3. https://docs.opencv.org/3.4.1/d1/d2d/classcv_1_1ml_1_1SVM.html  opencv官方文档

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值