#include <string>
#include <iostream>
#include <opencv2\opencv.hpp>
#include <opencv2\ml.hpp>
#include<fstream>
using namespace std;
using namespace cv;
using namespace ml;
int main()
{
////==========================读取图片创建训练数据==============================////
//将所有图片大小统一转化为8*16
const int imageRows = 8;
const int imageCols = 16;
//图片共有10类
const int classSum = 10;
//每类共20张图片
const int imagesSum = 20;
//每一行一个训练图片
//float trainingData[classSum*imagesSum][imageRows*imageCols] = { { 0 } };
Mat trainData0; // = Mat(classSum*imagesSum, imageRows*imageCols, CV_8UC1, Scalar::all(0));
//训练样本标签
//float labels[classSum*imagesSum] = { 0 };
string img_path = "C:\\Users\\wangzhenlin\\Desktop\\ann\\Image\\";
ifstream fin(img_path + "img.txt");
string str;
while (getline(fin, str)) {
if (str.length()) {
string imgname = img_path + str;
//cout << imgname << endl;
//getchar();
Mat src = imread(imgname, 0);
//imshow("aa", src);
//waitKey(0);
if (src.empty())
{
std::cout << "can not load image \n" << std::endl;
return -9;
}
Mat resizeImg, trainImg;
int k = 0;
//将所有图片大小统一转化为8*16
resize(src, resizeImg, Size(imageRows, imageCols), (0, 0), (0, 0), INTER_AREA);
//threshold(resizeImg, trainImg, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
threshold(resizeImg, trainImg, 0, 1, cv::THRESH_BINARY | cv::THRESH_OTSU);
Mat rowMat = trainImg.reshape(0, 1);
trainData0.push_back(rowMat);
//int m = 0;
//for (int j = 0; j < trainImg.rows; j++) {
// uchar *p = trainImg.ptr<uchar>(j);
// for (int k = 0; k < trainImg.cols; k++) {
// int index = k * j + k;
// trainingData[m][index] = p[k];
// }
//}
//m++;
}
}
// 设置标签数据
Mat label0 = Mat(classSum*imagesSum, classSum, CV_8UC1, Scalar::all(0));
//int a = 0;
int b = 0;
for (int i = 0; i < 200; i++)
{
b = i / 20;
//labels[i] = (float)b;
label0.at<uchar>(i, b) = 1.0;
//a++;
}
//训练样本数据及对应标签
//Mat trainingDataMat(classSum*imagesSum, imageRows*imageCols, CV_32FC1, trainingData);
//Mat labelsMat(classSum*imagesSum, classSum, CV_32FC1, labels);
//std::cout<<"trainingDataMat: \n"<<trainingDataMat<<"\n"<<std::endl;
//std::cout<<"labelsMat: \n"<<labelsMat<<"\n"<<std::endl;
////==========================训练部分==============================////
Ptr<ANN_MLP>model = ANN_MLP::create();
//Mat layerSizes = (Mat_<int>(1, 5) << imageRows * imageCols, 128, 128, 128, classSum);
Mat layerSizes = (Mat_<int>(1, 3) << imageRows * imageCols, 500, classSum);
model->setLayerSizes(layerSizes);
model->setTrainMethod(ANN_MLP::BACKPROP, 0.001, 0.1);
model->setActivationFunction(ANN_MLP::SIGMOID_SYM, 1.0, 1.0);
model->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS, 10000, 0.0001));
Mat trainDataFloat, lebalFloat;
trainData0.convertTo(trainDataFloat, CV_32FC1);
label0.convertTo(lebalFloat, CV_32FC1);
Ptr<TrainData> trainData = TrainData::create(trainDataFloat, ROW_SAMPLE, lebalFloat);
model->train(trainData);
//保存训练结果
model->save("MLPModel.xml");
////==========================预测部分==============================////
//读取测试图像
Mat test, dst;
test = imread(img_path + "1475068321.png", 0);;
//test = imread(img_path + "1475069602.png", 0);;
if (test.empty())
{
std::cout << "can not load image \n" << std::endl;
return -2;
}
resize(test, test, Size(imageRows, imageCols), (0, 0), (0, 0), INTER_AREA);
threshold(test, test, 0, 1, cv::THRESH_BINARY | cv::THRESH_OTSU);
Mat_<float> testMat(1, imageRows*imageCols);
testMat = test.reshape(0, 1);
//for (int i = 0; i < imageRows*imageCols; i++)
//{
// testMat.at<float>(0, i) = (float)test.at<uchar>(i / 8, i % 8);
//}
model->save("123.xml");
//使用训练好的MLP model预测测试图像
model->predict(testMat, dst);
std::cout << "testMat: \n" << testMat << "\n" << std::endl;
std::cout << "dst: \n" << dst << "\n" << std::endl;
double maxVal = 0;
Point maxLoc;
minMaxLoc(dst, NULL, &maxVal, NULL, &maxLoc);
std::cout << "测试结果:" << maxLoc.x << "置信度:" << maxVal * 100 << "%" << std::endl;
imshow("test", test);
waitKey(0);
return 0;
}
结果输出:
还有一种是基于KNN与随机森林的:
#include "opencv2\opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::ml;
int main()
{
Mat img = imread("123.png");
Mat gray;
cvtColor(img, gray, CV_BGR2GRAY);
int b = 20;
int m = gray.rows / b; //原图为1000*2000
int n = gray.cols / b; //裁剪为5000个20*20的小图块
Mat data, labels; //特征矩阵
for (int i = 0; i < n; i++)
{
int offsetCol = i*b; //列上的偏移量
for (int j = 0; j < m; j++)
{
int offsetRow = j*b; //行上的偏移量
//截取20*20的小块
Mat tmp;
gray(Range(offsetRow, offsetRow + b), Range(offsetCol, offsetCol + b)).copyTo(tmp);
data.push_back(tmp.reshape(0, 1)); //序列化后放入特征矩阵
labels.push_back((int)j / 5); //对应的标注
}
}
data.convertTo(data, CV_32F); //uchar型转换为cv_32f
int samplesNum = data.rows;
int trainNum = 3000;
Mat trainData, trainLabels;
trainData = data(Range(0, trainNum), Range::all()); //前3000个样本为训练数据
trainLabels = labels(Range(0, trainNum), Range::all());
//训练样本数据及对应标签
//Mat trainingDataMat(classSum*imagesSum, imageRows*imageCols, CV_32FC1, trainingData);
//Mat labelsMat(classSum*imagesSum, classSum, CV_32SC1, labels);
//std::cout<<"trainingDataMat: \n"<<trainingDataMat<<"\n"<<std::endl;
//std::cout<<"labelsMat: \n"<<labelsMat<<"\n"<<std::endl;
////==========================训练部分==============================////
Ptr<SVM> svm = SVM::create();//SVM分类器
svm->setType(SVM::C_SVC);
svm->setC(0.01);
svm->setKernel(SVM::LINEAR);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 3000, 1e-6));
std::cout << "Starting training..." << endl;
svm->train(trainData, ROW_SAMPLE, trainLabels);//训练分类器
std::cout << "Finishing training..." << endl;
//使用KNN算法
int K = 5;
Ptr<TrainData> tData = TrainData::create(trainData, ROW_SAMPLE, trainLabels);
Ptr<KNearest> model = KNearest::create();
model->setDefaultK(K);
model->setIsClassifier(true);
model->train(tData);
double ktrain_hr = 0, ktest_hr = 0;
// compute prediction error on train and test data
for (int i = 0; i < samplesNum; i++)
{
Mat sample = data.row(i);
float r = model->predict(sample); //对所有行进行预测
//预测结果与原结果相比,相等为1,不等为0
r = std::abs(r - labels.at<int>(i)) <= FLT_EPSILON ? 1.f : 0.f;
if (i < trainNum)
ktrain_hr += r; //累积正确数
else
ktest_hr += r;
}
ktest_hr /= samplesNum - trainNum;
ktrain_hr = trainNum > 0 ? ktrain_hr / trainNum : 1.;
printf("accuracy: train = %.1f%%, test = %.1f%%\n",
ktrain_hr*100., ktest_hr*100.);
//预测分类
double train_hr = 0, test_hr = 0;
// compute prediction error on train and test data
for (int i = 0; i < samplesNum; i++)
{
Mat sample = data.row(i);
float r = svm->predict(sample); //对所有行进行预测
//预测结果与原结果相比,相等为1,不等为0
r = std::abs(r - labels.at<int>(i)) <= FLT_EPSILON ? 1.f : 0.f;
if (i < trainNum)
train_hr += r; //累积正确数
else
test_hr += r;
}
test_hr /= samplesNum - trainNum;
train_hr = trainNum > 0 ? train_hr / trainNum : 1.;
printf("accuracy: train = %.1f%%, test = %.1f%%\n",
train_hr*100., test_hr*100.);
waitKey(0);
getchar();
return 0;
}