#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/objdetect.hpp"
#include <opencv2/ml.hpp>
using namespace cv::ml;
using namespace cv;
using namespace std;
string pathName = "digits.png";
int SZ = 20;
float affineFlags = WARP_INVERSE_MAP | INTER_LINEAR;
//倾斜矫正
Mat deskew(Mat& img) {
Moments m = moments(img);
if (abs(m.mu02) < 1e-2) {
return img.clone();
}
float skew = m.mu11 / m.mu02;
Mat warpMat = (Mat_<float>(2, 3) << 1, skew, -0.5*SZ*skew, 0, 1, 0); //2*3变换矩阵
Mat imgOut = Mat::zeros(img.rows, img.cols, img.type());
warpAffine(img, imgOut, warpMat, imgOut.size(), affineFlags);
return imgOut;
}
//加载训练测试数据集标签
void loadTrainTestLabel(string &pathName, vector<Mat> &trainCells, vector<int> &trainLabels) {
Mat img = imread(pathName, CV_LOAD_IMAGE_GRAYSCALE);
int ImgCount = 0;
for (int i = 0; i < img.rows; i = i + SZ)
{
for (int j = 0; j < img.cols; j = j + SZ)
{
Mat digitImg = (img.colRange(j, j + SZ).rowRange(i, i + SZ)).clone();
trainCells.push_back(digitImg);
ImgCount++;
}
}
cout << "Image Count : " << ImgCount << endl;
float digitClassNumber = 0;
for (int z = 0; z<ImgCount; z++)
{
if (z % 500 == 0 && z != 0)
{
digitClassNumber = digitClassNumber + 1;
}
trainLabels.push_back(digitClassNumber);
}
}
// 创建倾斜矫正后的训练集测试集
void CreateDeskewedTrainTest(vector<Mat> &deskewedTrainCells, vector<Mat> &trainCells) {
for (int i = 0; i<trainCells.size(); i++) {
Mat deskewedImg = deskew(trainCells[i]);
deskewedTrainCells.push_back(deskewedImg);
}
}
//HOG特征描述子
HOGDescriptor hog(
Size(20, 20), //winSize
Size(10, 10), //blocksize
Size(5, 5), //blockStride,
Size(10, 10), //cellSize,
9, //nbins,
1, //derivAper,
-1, //winSigma,
0, //histogramNormType,
0.2, //L2HysThresh,
0,//gammal correction,
64,//nlevels=64
1);
//创建训练测试HOG特征,并将计算结果保存至
void CreateTrainTestHOG(vector<vector<float> > &trainHOG, vector<Mat> &deskewedtrainCells) {
//train hog大小为num*hogsize
for (int y = 0; y<deskewedtrainCells.size(); y++) {
vector<float> descriptors;
hog.compute(deskewedtrainCells[y], descriptors, Size(2, 2), Size(0, 0));
trainHOG.push_back(descriptors);
}
}
void ConvertVectortoMatrix(vector<vector<float> > &trainHOG, Mat &trainMat)
{
int descriptor_size = trainHOG[0].size();//第一个样本的特征大小
for (int i = 0; i<trainHOG.size(); i++) {
for (int j = 0; j<descriptor_size; j++) {
trainMat.at<float>(i, j) = trainHOG[i][j];
}
}
}
void getSVMParams(SVM *svm)
{
cout << "Kernel type : " << svm->getKernelType() << endl;
cout << "Type : " << svm->getType() << endl;
cout << "C : " << svm->getC() << endl;
cout << "Degree : " << svm->getDegree() << endl;
cout << "Nu : " << svm->getNu() << endl;
cout << "Gamma : " << svm->getGamma() << endl;
}
void SVMtrain(Mat &trainMat, vector<int> &trainLabels) {
Ptr<SVM> svm = SVM::create();
svm->setGamma(0.50625);
svm->setC(12.5);
svm->setKernel(SVM::RBF);
svm->setType(SVM::C_SVC);
Ptr<TrainData> td = TrainData::create(trainMat, ROW_SAMPLE, trainLabels);
svm->train(td);
//svm->trainAuto(td);
svm->save("model4.yml");
getSVMParams(svm);
}
int main() {
/*检测部分*/
/*Ptr<SVM> svm = Algorithm::load<SVM>("model4.yml");*/ //创建对象并初始化
Ptr<SVM> svm = SVM::create();//创建对象
svm = svm->load("model4.yml");//初始化
/*cout << svm->getVarCount() << endl;*/
if (!svm)
{
cout << "Load file failed..." << endl;
}
Mat img = imread(pathName, 0);
if (img.empty())
{
cout << "not exist" << endl;
return -1;
}
Mat test = (img.colRange(0, 20).rowRange(60, 80)).clone();
/*imshow("te", test);*/
Mat skew = deskew(test);
/*imshow("sk", skew);*/
vector<float> m_descriptor;
hog.compute(skew, m_descriptor, Size(8, 8), Size(0, 0));//检测窗口移动步长
Mat img_hog(1, m_descriptor.size(), CV_32FC1);
for (int i = 0; i < m_descriptor.size(); i++)
{
img_hog.at<float>(0, i) = m_descriptor[i];
}
/*int r = svm->predict(m_descriptor);*/
int r =svm->predict(img_hog);
cout << r << endl;
/*训练部分*/
//vector<Mat> trainCells;
//
//vector<int> trainLabels;
//
//loadTrainTestLabel(pathName, trainCells,trainLabels);
//vector<Mat> deskewedTrainCells;
//
//CreateDeskewedTrainTest(deskewedTrainCells, trainCells);
//std::vector<std::vector<float> > trainHOG;
//
//CreateTrainTestHOG(trainHOG, deskewedTrainCells);
//int descriptor_size = trainHOG[0].size(); //每张图片的特征数
//cout << "Descriptor Size : " << descriptor_size << endl;
//Mat trainMat(trainHOG.size(), descriptor_size, CV_32FC1);
//
//ConvertVectortoMatrix(trainHOG, trainMat);
//Mat testResponse;
//SVMtrain(trainMat,trainLabels);
waitKey(0);
return 0;
}