#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。