简单实验数据实现实验流程
训练数据
第一类 长疵
第二类 点疵
测试数据
一个长,一个短
代码
#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;
}
结果