生丝疵点分类 SVM 实验一

简单实验数据实现实验流程

训练数据

第一类 长疵

第二类 点疵

测试数据

一个长,一个短

代码

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>

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



// 先实现长疵 和 点疵 的二分类

float get_Area(Mat &iamge)//统计白色像素点的个数
{
	threshold(iamge, iamge, 0, 255, THRESH_BINARY);
	float area = 0.;
	//通过迭代器访问图像的像素点
	Mat_<uchar>::iterator itor = iamge.begin<uchar>();
	Mat_<uchar>::iterator itorEnd = iamge.end<uchar>();
	for (; itor != itorEnd; itor++) {
		if ((*itor) > 254){
			//白色像素
			area++;
		}

	}
	return area;

}

float get_wh(Mat & image)
{
	float w, h;
	threshold(image, image, 0, 255, THRESH_BINARY);
	float ration;// 返回的宽 高 之比, 长条形 宽大于高
	Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
	morphologyEx(image, image, MORPH_OPEN, element);
	vector<vector<Point> > contours;//检测到的轮廓,每条轮廓线都以点向量的形式存储
	vector<Vec4i> hierarchy;//包含有关图像拓扑的信息
	findContours(image, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE, Point());
	for (int i = 0; i < contours.size(); i++) {
		Rect rects = boundingRect(contours[i]);
		int area = rects.width * rects.height;
		if (area > 10) {//排除过小的噪声被当成轮廓
			w = rects.width;
			h = rects.height;
		}
	}
	ration = w / h;
	return ration;

}


String path;
Mat img;

const int NTRAINING_SAMPLES =2; //  每类分类样本的数目
map<int, string> mapLabel = { {1, "长疵",},
						{2, "点疵",}};


int main(int argc, char** argv)
{
	String pathName;
	Mat trainData(2 * NTRAINING_SAMPLES, 2, CV_32F);//保存坐标信息,4行*2列
	Mat labels(2 * NTRAINING_SAMPLES, 1, CV_32S);//保存标签信息,4行*1列
	//准备训练数据
	//线性部分,样本先简单设置
	//第一类
	Mat trainClass = trainData.rowRange(0, NTRAINING_SAMPLES);//4行全选
	Mat c = trainClass.colRange(0, 1);//选第一列的2个参数 我设置为面积
	path = "E:\\研究生\\数字图像处理\\c++\\生丝瑕疵检测\\Project1\\train\\1\\";
	for (int i = 0; i < NTRAINING_SAMPLES; i++) {
		pathName = path + to_string(i+1) + ".jpg";
		Mat img = imread(pathName, 0);
		c.at<float>(i,0) = get_Area(img);
	}
	c = trainClass.colRange(1, 2);//选第2列的2个参数 宽高比
	for (int i = 0; i < NTRAINING_SAMPLES; i++) {
		pathName = path + to_string(i + 1) + ".jpg";
		Mat img = imread(pathName, 0);
		c.at<float>(i, 0) = get_wh(img);
	}
	//第二类的数据
	trainClass = trainData.rowRange(NTRAINING_SAMPLES,2* NTRAINING_SAMPLES);//4行全选
	c = trainClass.colRange(0, 1);//选第一列的2个参数 我设置为面积
	path = "E:\\研究生\\数字图像处理\\c++\\生丝瑕疵检测\\Project1\\train\\2\\";
	for (int i = 0; i < NTRAINING_SAMPLES; i++) {
		pathName = path + to_string(i + 1) + ".jpg";
		Mat img = imread(pathName, 0);
		c.at<float>(i, 0) = get_Area(img);
	}
	c = trainClass.colRange(1, 2);//选第2列的2个参数 宽高比
	for (int i = 0; i < NTRAINING_SAMPLES; i++) {
		pathName = path + to_string(i + 1) + ".jpg";
		Mat img = imread(pathName, 0);
		c.at<float>(i, 0) = get_wh(img);
	}
	//训练数据准备完成
	cout <<"train data : "<<"\n"<< trainData << endl;
	// 类别标签设置
	labels.rowRange(0, NTRAINING_SAMPLES).setTo(1);  // Class 1
	labels.rowRange(NTRAINING_SAMPLES, 2 * NTRAINING_SAMPLES).setTo(2);  // Class 2
	cout <<"labels : " <<"\n" <<labels << endl;

	//SVM 
	cout << "Starting training process" << endl;
	//初始化
	Ptr<SVM> svm = SVM::create();
	svm->setType(SVM::C_SVC);
	svm->setC(0.1);
	svm->setKernel(SVM::LINEAR);
	svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, (int)1e7, 1e-6));
	//训练
	svm->train(trainData, ROW_SAMPLE, labels);
	cout << "Finished training process" << endl;

	// 数据显示
	const int WIDTH = 512, HEIGHT = 512;// 最后画的图的尺寸
	Mat I = Mat::zeros(HEIGHT, WIDTH, CV_8UC3);// 三通道黑色背景图像
	Vec3b green(0, 100, 0), blue(100, 0, 0);
	for (int i = 0; i < I.rows; i++)
	{
		for (int j = 0; j < I.cols; j++)
		{
			Mat sampleMat = (Mat_<float>(1, 2) << j, i);
			float response = svm->predict(sampleMat);

			if (response == 1) I.at<Vec3b>(i, j) = green;
			else if (response == 2) I.at<Vec3b>(i, j) = blue;
		}
	}
	//显示训练数据
	int thick = -1;
	float px, py;
	// Class 1
	for (int i = 0; i < NTRAINING_SAMPLES; i++)
	{
		px = trainData.at<float>(i, 0);
		py = trainData.at<float>(i, 1);
		circle(I, Point((int)px, (int)py), 3, Scalar(0, 255, 0), thick);
	}
	// Class 2
	for (int i = NTRAINING_SAMPLES; i < 2 * NTRAINING_SAMPLES; i++)
	{
		px = trainData.at<float>(i, 0);
		py = trainData.at<float>(i, 1);
		circle(I, Point((int)px, (int)py), 3, Scalar(255, 0, 0), thick);
	}

	//显示支持向量
	thick = 2;
	Mat sv = svm->getUncompressedSupportVectors();

	for (int i = 0; i < sv.rows; i++)
	{
		const float* v = sv.ptr<float>(i);
		circle(I, Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), thick);
	}

	imshow("SVM for Non-Linear Training Data", I); // show it to the user

	//预测
	String testPath = "E:\\研究生\\数字图像处理\\c++\\生丝瑕疵检测\\Project1\\train\\t1.jpg";
	Mat testData(1, 2, CV_32F);//测试数据 1行 2列
	Mat testImg = imread(testPath, 0);
	imshow("test image", testImg);
	testData.at<float>(0, 0) = get_Area(testImg);
	testData.at<float>(0, 1) = get_wh(testImg);
	cout << "test data" <<testData<< endl;
	float testLabel = svm->predict(testData);
	cout <<"测试结果"<< mapLabel[testLabel] << endl;
	waitKey(0);
	destroyAllWindows();

	return 0;
   
}

结果

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值