opencv 学习之 SVM / ANN 图片分类(OPENCV3.2)

#include <string>
#include <iostream>
#include <vector> 

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

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



int SVM_TEST()
{
	//训练2组数据,每组4帧
	int labels[8] = { -1, -1, -1, -1, 1, 1, 1, 1 };
	Mat labelsMat(8, 1, CV_32SC1, labels);

	//样本宽高
	int smpW = 540;
	int smpH = 360;

	//将样本的值逐像素赋给训练图像
	Mat trainMat(8, smpW * smpH, CV_32FC1);
	for (int i = 0; i < 2; i++)
	{
		for (int j = 1; j < 5; j++)
		{
			string path = format("E:\\video\\tmp\\Img\\%d%d.bmp", i, j);
			Mat img = imread(path, 0);
			//Canny(img, img, 50, 100);

			int index1 = i * 4 + j - 1;
			float * trainData = trainMat.ptr<float>(index1);

			for (int h = 0; h < smpH; h++)
			{
				uchar * imgData = img.ptr<uchar>(h);
				for (int w = 0; w < smpW; w++)
				{
					int index2 = h*smpW + w;
					trainData[index2] = imgData[w];
				}
			}
		}
	}
	
	//Ptr<SVM> svm = SVM::create();
	//svm->setType(SVM::C_SVC);
	//svm->setKernel(SVM::LINEAR);
	//svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));

	////设置训练数据 
	//Ptr<TrainData> tData = TrainData::create(trainMat, ROW_SAMPLE, labelsMat);
	//svm->train(tData);
	//svm->save("d:\\data.xml");

	Ptr<SVM> svm = SVM::load("d:\\data.xml");

	for (int i = 0; i < 2; i++)
	{
		for (int j = 5; j < 6; j++)
		{
			Mat testMat(1, smpW * smpH, CV_32FC1);
			float * testData = testMat.ptr<float>(0);

			string path = format("E:\\video\\tmp\\Img\\%d%d.bmp", i, j);
			Mat img = imread(path, 0);
			//Canny(img, img, 50, 100);

			for (int h = 0; h < smpH; h++)
			{
				uchar * imgData = img.ptr<uchar>(h);
				for (int w = 0; w < smpW; w++)
				{
					int index2 = h*smpW + w;
					testData[index2] = imgData[w] * 1.0;
				}
			}

			Mat ret(1, 1, CV_32S);
			float response = svm->predict(testMat, ret);  //进行预测,返回1或-1
			cout << response << endl;
			float * data = ret.ptr<float>(0);
			cout << data[0] << endl;
			waitKey(10);
		}
	}
	return 0;
}


int ANN_TEST()
{
	// 540 x 360 矩阵
	int smpW = 540;
	int smpH = 360;
	
	float labels[8] = { 0,0,0,0,1,1,1,1 };  // 每个样本数据对应的输出	
	Mat labelsMat(8, 1, CV_32FC1, labels);
	cout << labelsMat << endl;

	// 训练样本
	Mat trainMat(8, smpW * smpH, CV_32FC1);
	for (int i = 0; i < 2; i++)
	{
		for (int j = 1; j < 5; j++)
		{
			string path = format("E:\\video\\tmp\\Img\\%d%d.bmp", i, j);
			Mat img = imread(path, 0);
			if (img.empty())
			{
				return 0;
			}
			//Canny(img, img, 50, 100);

			int index1 = i * 4 + j - 1;
			float * trainData = trainMat.ptr<float>(index1);

			for (int h = 0; h < smpH; h++)
			{
				uchar * imgData = img.ptr<uchar>(h);
				for (int w = 0; w < smpW; w++)
				{
					int index2 = h*smpW + w;
					trainData[index2] = imgData[w];
				}
			}
		}
	}

	//// BP 模型创建和参数设置
	//Ptr<ANN_MLP> bp = ANN_MLP::create();

	//Mat layerSizes = (Mat_<int>(1, 3) << smpW * smpH, 6, 1);
	//bp->setLayerSizes(layerSizes);

	//bp->setTrainMethod(ANN_MLP::BACKPROP, 0.1, 0.1);
	//bp->setActivationFunction(ANN_MLP::SIGMOID_SYM);
	//bp->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 10000, /*FLT_EPSILON*/1e-6));

	//// 保存训练好的神经网络参数
	//bool trained = bp->train(trainMat, ROW_SAMPLE, labelsMat);
	//if (trained) 
	//{
	//	bp->save("d:\\bp_param.xml");
	//}

	// 创建训练好的神经网络
	Ptr<ANN_MLP> bp = ANN_MLP::load("d:\\bp_param.xml");

	for (int i = 0; i < 2; i++)
	{
		for (int j = 5; j < 6; j++)
		{
			Mat testMat(1, smpW * smpH, CV_32FC1);
			float * testData = testMat.ptr<float>(0);

			string path = format("E:\\video\\tmp\\Img\\%d%d.bmp", i, j);
			Mat img = imread(path, 0);
			//Canny(img, img, 50, 100);

			for (int h = 0; h < smpH; h++)
			{
				uchar * imgData = img.ptr<uchar>(h);
				for (int w = 0; w < smpW; w++)
				{
					int index2 = h*smpW + w;
					testData[index2] = imgData[w] * 1.0;
				}
			}

			Mat responseMat;
			bp->predict(testMat, responseMat);
			float response = responseMat.ptr<float>(0)[0];
			cout << response << endl;
			float * data = responseMat.ptr<float>(0);
			cout << data[0] << endl;
			waitKey(10);
		}
	}

	waitKey(0);
	return 0;
}


int main()
{
	SVM_TEST();
	ANN_TEST();
}

VS2017  +  OPENCV3.2

用法与 OPENCV2 有较大差异。另外,特征文件载入时与 OPENCV2 差异最大,需要直接载入,不再先创建再载入。否则报内存错误。然后需要注意的是,SVM/KNN 的 label 类型是 CV_32SC1,而 ANN 的 label 类型是 CV_32FC1。

猜你喜欢

转载自blog.csdn.net/u010477528/article/details/77863141