1.朴素贝叶斯:
在使用时,有一个前提假设:各特征独立。在用贝叶斯公式之前,最好先看下全概率公式。用c表示类别,f表示特征。则贝叶斯课表示为:
在计算时,记得要拉普拉斯平滑,具体公式看西瓜书。还可以看看数据挖掘领域十大经典算法之—朴素贝叶斯算法和机器学习之朴素贝叶斯(NB)分类算法与Python实现。
OpenCV下的NormalBayesClassifier(训练的时间太长,不太好用):
void main()
{
Mat classes;
Mat trainingData;
Mat trainingImage;
Mat trainingLables;
string imgname;
ifstream fin("C:/Users/Administrator/Desktop/num/0/zero.txt");//C:/Users/Administrator/Desktop/num/0/0.txt
while (getline(fin, imgname))
{
imgname = "C:/Users/Administrator/Desktop/num/0/" + imgname;//C:/Users/Administrator/Desktop/num/0/
Mat img = imread(imgname,0);
img = img.reshape(1, 1);
trainingImage.push_back(img);
trainingLables.push_back(0);
}
cout << "loading 0---" << endl;
string imgname_2;
ifstream fin_2("C:/Users/Administrator/Desktop/num/1/one.txt");//C:/Users/Administrator/Desktop/num/1/1.txt
while (getline(fin_2, imgname_2))
{
imgname_2 = "C:/Users/Administrator/Desktop/num/1/" + imgname_2;//C:/Users/Administrator/Desktop/num/1/
Mat img = imread(imgname_2,0);
img = img.reshape(1, 1);
trainingImage.push_back(img);
trainingLables.push_back(1);
}
cout << "loading 1---" << endl;
Mat(trainingImage).copyTo(trainingData);
trainingData.convertTo(trainingData,CV_32FC1);
Mat(trainingLables).copyTo(classes);
/*classes.convertTo(classes,CV_32FC1);*/
Ptr<NormalBayesClassifier> Nb= NormalBayesClassifier::create();
cout << "trainging---" << endl;
Nb->train(trainingData, cv::ml::ROW_SAMPLE, classes);
//Nb->save("Nb.xml");
cout << "finish---save model" << endl;
Mat classes_test;
Mat trainingData_test;
Mat trainingImage_test;
Mat trainingLables_test;
string imgname_test;
ifstream fin_test("C:/Users/Administrator/Desktop/num/0/zero.txt");//C:/Users/Administrator/Desktop/num/test/0/0.txt
while (getline(fin_test, imgname_test))
{
imgname_test = "C:/Users/Administrator/Desktop/num/0/" + imgname_test;
Mat img = imread(imgname_test,0);
img = img.reshape(1, 1);
trainingImage_test.push_back(img);
trainingLables_test.push_back(0);
}
string imgname_2_test;
ifstream fin_2_test("C:/Users/Administrator/Desktop/num/1/one.txt");//C:/Users/Administrator/Desktop/num/test/1/1.txt
while (getline(fin_2_test, imgname_2_test))
{
imgname_2_test = "C:/Users/Administrator/Desktop/num/1/" + imgname_2_test;
Mat img = imread(imgname_2_test,0);
img = img.reshape(1, 1);
trainingImage_test.push_back(img);
trainingLables_test.push_back(1);
}
Mat(trainingImage_test).copyTo(trainingData_test);
trainingData_test.convertTo(trainingData_test, CV_32FC1);
Mat(trainingLables_test).copyTo(classes_test);
Mat re;
Mat prob;
Mat res;
Nb->predictProb(trainingData_test, re,prob);
cout<<"re:" <<endl<< re << endl;
cout <<"prob:"<<endl<<prob << endl;
waitKey(0);
}
期间报错的主要原因都是:训练时或者测试时未正确读取图片。这种算法不太好,训练耗时太长。问题参考了:Python图像处理(12):贝叶斯分类器,在opencv3中实现机器学习之:利用正态贝叶斯分类,练习。
2.KNN:
knn既可以用于分类,也可以用于回归。knn的基本步骤就是计算距离,排序,选择距离最小的K个点,找那K个点里找label次数最多的那个点即为所分的得类。推荐算法用的比较多。
OpenCV下的KNN:
void main()
{
Mat classes;
Mat trainingData;
Mat trainingImage;
Mat trainingLables;
string imgname;
ifstream fin("C:/Users/Administrator/Desktop/num/0/0.txt");//C:/Users/Administrator/Desktop/num/0/0.txt
while (getline(fin, imgname))
{
imgname = "C:/Users/Administrator/Desktop/num/0/" + imgname;//C:/Users/Administrator/Desktop/num/0/
Mat img = imread(imgname,0);
if (!img.data)
{
cout << "no img" << endl;
break;
}
img = img.reshape(1, 1);
trainingImage.push_back(img);
trainingLables.push_back(0);
}
cout << "loading 0---" << endl;
string imgname_2;
ifstream fin_2("C:/Users/Administrator/Desktop/num/1/1.txt");//C:/Users/Administrator/Desktop/num/1/1.txt
while (getline(fin_2, imgname_2))
{
imgname_2 = "C:/Users/Administrator/Desktop/num/1/" + imgname_2;//C:/Users/Administrator/Desktop/num/1/
Mat img = imread(imgname_2,0);
if (!img.data)
{
cout << "no img" << endl;
break;
}
img = img.reshape(1, 1);
trainingImage.push_back(img);
trainingLables.push_back(1);
}
cout << "loading 1---" << endl;
Mat(trainingImage).copyTo(trainingData);
trainingData.convertTo(trainingData,CV_32FC1);
Mat(trainingLables).copyTo(classes);
classes.convertTo(classes,CV_32FC1);
cout << trainingData.cols << endl;
Ptr<KNearest> knn= KNearest::create();
knn->setDefaultK(4);
knn->setIsClassifier(true);
knn->setAlgorithmType(cv::ml::KNearest::BRUTE_FORCE);
cout << "trainging---" << endl;
knn->train(trainingData, cv::ml::ROW_SAMPLE, classes);
//knn->save("knn.xml");
cout << "finish---save model" << endl;
Mat classes_test;
Mat trainingData_test;
Mat trainingImage_test;
Mat trainingLables_test;
string imgname_test;
ifstream fin_test("C:/Users/Administrator/Desktop/num/test/0/0.txt");//C:/Users/Administrator/Desktop/num/0/zero.txt
while (getline(fin_test, imgname_test))
{
imgname_test = "C:/Users/Administrator/Desktop/num/test/0/" + imgname_test;
Mat img = imread(imgname_test,0);
img = img.reshape(1, 1);
cout << "--" << img.size() << endl;
if (!img.data)
{
cout << "no img" << endl;
break;
}
trainingImage_test.push_back(img);
trainingLables_test.push_back(0);
}
string imgname_2_test;
ifstream fin_2_test("C:/Users/Administrator/Desktop/num/test/1/1.txt");//C:/Users/Administrator/Desktop/num/1/one.txt
while (getline(fin_2_test, imgname_2_test))
{
imgname_2_test = "C:/Users/Administrator/Desktop/num/test/1/" + imgname_2_test;
Mat img = imread(imgname_2_test,0);
if (!img.data)
{
cout << "no img" << endl;
break;
}
img = img.reshape(1, 1);
cout << "--" << img.size() << endl;
trainingImage_test.push_back(img);
trainingLables_test.push_back(1);
}
Mat(trainingImage_test).copyTo(trainingData_test);
trainingData_test.convertTo(trainingData_test, CV_32FC1);
Mat(trainingLables_test).copyTo(classes_test);
classes_test.convertTo(classes_test,CV_32FC1);
Mat re;
knn->predict(trainingData_test,re);
cout<<calculateAccuracyPercent(classes_test,re)<<endl;
waitKey(0);
}
调试过程中报错原因有:1.最后Mat的类型(train和test的要一致),2.是否正确读取到图片。主要参考了:在opencv3中的机器学习算法 ,OpenCV3.3中 K-最近邻法(KNN)接口简介及使用。
3.LogisticRegression:
OpenCV中的LogisticRegression(LogisticRegression):
训练:
void main()
{
Mat classes;
Mat trainingData;
Mat trainingImage;
Mat trainingLables;
string imgname;
ifstream fin("C:/Users/Administrator/Desktop/num/0/0.txt");
while (getline(fin, imgname))
{
imgname = "C:/Users/Administrator/Desktop/num/0/" + imgname;
Mat img = imread(imgname);
img = img.reshape(1, 1);
trainingImage.push_back(img);
trainingLables.push_back(0);
}
cout << "loading 0---" << endl;
string imgname_2;
ifstream fin_2("C:/Users/Administrator/Desktop/num/1/1.txt");
while (getline(fin_2, imgname_2))
{
imgname_2 = "C:/Users/Administrator/Desktop/num/1/" + imgname_2;
Mat img = imread(imgname_2);
img = img.reshape(1, 1);
trainingImage.push_back(img);
trainingLables.push_back(1);
}
cout << "loading 1---" << endl;
Mat(trainingImage).copyTo(trainingData);
trainingData.convertTo(trainingData,CV_32FC1);
Mat(trainingLables).copyTo(classes);
classes.convertTo(classes,CV_32FC1);
Ptr<LogisticRegression> lr= LogisticRegression::create();
lr->setLearningRate(0.0001);
lr->setIterations(100);
lr->setRegularization(cv::ml::LogisticRegression::REG_DISABLE);
lr->setTrainMethod(cv::ml::LogisticRegression::MINI_BATCH);
lr->setMiniBatchSize(1);
cout << "trainging---" << endl;
lr->train(trainingData, cv::ml::ROW_SAMPLE, classes);
lr->save("lr.xml");
cout << "finish---save model" << endl;
waitKey(0);
}
调试过程中报错:
OpenCV Error: Bad argument (data must be of floating type) in cv::ml::LogisticRe
gressionImpl::predict, file F:\OpenCV3.3\opencv\sources\modules\ml\src\lr.cpp, l
ine 250
是因为类型不是CV_32FC1,但是convertTo后还是出错。原因在于直接写成了src.reshape(1, 1);,改成src=src.reshape(1, 1);就不会报错了。
测试:
static float calculateAccuracyPercent(const Mat &original, const Mat &predicted)
{
return 100 * (float)countNonZero(original == predicted) / predicted.rows;
}
void main()
{
Mat src = imread("C:/Users/Administrator/Desktop/num/1/1.bmp");
src=src.reshape(1, 1);
src.convertTo(src,CV_32FC1);
Ptr<LogisticRegression> lr = LogisticRegression::load("lr.xml");
Mat re;
float t = 0;
t=lr->predict(src,re);
cout << re << endl;
cout << "t:" << t << endl;
Mat label;
label.push_back(1);
cout << label<<endl;
cout << label.size() << endl;
cout << re.size() << endl;
cout << calculateAccuracyPercent(label, re) << endl;
}
测试过程报错:
OpenCV Error: Sizes of input arguments do not match (The operation is neither 'a
rray op array' (where arrays have the same size and the same type), nor 'array o
p scalar', nor 'scalar op array') in cv::compare, file F:\OpenCV3.3\opencv\sourc
es\modules\core\src\arithm.cpp, line 1256
是因为这句:label.convertTo(label,CV_32FC1);,删掉之后就可以了(目前并不知道为什么这句会导致报错)。
批量测试:
void main()
{
Mat classes;
Mat trainingData;
Mat trainingImage;
Mat trainingLables;
string imgname;
ifstream fin("C:/Users/Administrator/Desktop/num/test/0/0.txt");
while (getline(fin, imgname))
{
imgname = "C:/Users/Administrator/Desktop/num/test/0/" + imgname;
Mat img = imread(imgname);
img = img.reshape(1, 1);
trainingImage.push_back(img);
trainingLables.push_back(0);
}
string imgname_2;
ifstream fin_2("C:/Users/Administrator/Desktop/num/test/1/1.txt");
while (getline(fin_2, imgname_2))
{
imgname_2 = "C:/Users/Administrator/Desktop/num/test/1/" + imgname_2;
Mat img = imread(imgname_2);
img = img.reshape(1, 1);
trainingImage.push_back(img);
trainingLables.push_back(1);
}
Mat(trainingImage).copyTo(trainingData);
trainingData.convertTo(trainingData, CV_32FC1);
Mat(trainingLables).copyTo(classes);
Ptr<LogisticRegression> lr = LogisticRegression::load("lr.xml");
Mat re;
lr->predict(trainingData,re);
cout<<"acc:"<<calculateAccuracyPercent(classes, re)<<"%"<< endl;
}
4.DTrees:
OpenCV下的DTrees:
void main()
{
Mat classes;
Mat trainingData;
Mat trainingImage;
Mat trainingLables;
string imgname;
ifstream fin("C:/Users/Administrator/Desktop/num/0/0.txt");//C:/Users/Administrator/Desktop/num/0/0.txt
while (getline(fin, imgname))
{
imgname = "C:/Users/Administrator/Desktop/num/0/" + imgname;//C:/Users/Administrator/Desktop/num/0/
Mat img = imread(imgname,0);
if (!img.data)
{
cout << "no img" << endl;
break;
}
img = img.reshape(1, 1);
trainingImage.push_back(img);
trainingLables.push_back(0);
}
cout << "loading 0---" << endl;
string imgname_2;
ifstream fin_2("C:/Users/Administrator/Desktop/num/1/1.txt");//C:/Users/Administrator/Desktop/num/1/1.txt
while (getline(fin_2, imgname_2))
{
imgname_2 = "C:/Users/Administrator/Desktop/num/1/" + imgname_2;//C:/Users/Administrator/Desktop/num/1/
Mat img = imread(imgname_2,0);
if (!img.data)
{
cout << "no img" << endl;
break;
}
img = img.reshape(1, 1);
trainingImage.push_back(img);
trainingLables.push_back(1);
}
cout << "loading 1---" << endl;
Mat(trainingImage).copyTo(trainingData);
trainingData.convertTo(trainingData,CV_32FC1);
Mat(trainingLables).copyTo(classes);
classes.convertTo(classes,CV_32FC1);
Ptr<DTrees> dtree= DTrees::create();
dtree->setMaxCategories(4);
dtree->setMaxDepth(10);
dtree->setMinSampleCount(10);
dtree->setCVFolds(0);
dtree->setUseSurrogates(false);
dtree->setUse1SERule(false);
dtree->setTruncatePrunedTree(false);
dtree->setRegressionAccuracy(0);
dtree->setPriors(cv::Mat());
cout << "trainging---" << endl;
dtree->train(trainingData, cv::ml::ROW_SAMPLE, classes);
//knn->save("knn.xml");
cout << "finish---save model" << endl;
Mat classes_test;
Mat trainingData_test;
Mat trainingImage_test;
Mat trainingLables_test;
string imgname_test;
ifstream fin_test("C:/Users/Administrator/Desktop/num/test/0/0.txt");//C:/Users/Administrator/Desktop/num/0/zero.txt
while (getline(fin_test, imgname_test))
{
imgname_test = "C:/Users/Administrator/Desktop/num/test/0/" + imgname_test;
Mat img = imread(imgname_test,0);
img = img.reshape(1, 1);
cout << "--" << img.size() << endl;
if (!img.data)
{
cout << "no img" << endl;
break;
}
trainingImage_test.push_back(img);
trainingLables_test.push_back(0);
}
string imgname_2_test;
ifstream fin_2_test("C:/Users/Administrator/Desktop/num/test/1/1.txt");//C:/Users/Administrator/Desktop/num/1/one.txt
while (getline(fin_2_test, imgname_2_test))
{
imgname_2_test = "C:/Users/Administrator/Desktop/num/test/1/" + imgname_2_test;
Mat img = imread(imgname_2_test,0);
if (!img.data)
{
cout << "no img" << endl;
break;
}
img = img.reshape(1, 1);
cout << "--" << img.size() << endl;
trainingImage_test.push_back(img);
trainingLables_test.push_back(1);
}
Mat(trainingImage_test).copyTo(trainingData_test);
trainingData_test.convertTo(trainingData_test, CV_32FC1);
Mat(trainingLables_test).copyTo(classes_test);
classes_test.convertTo(classes_test,CV_32FC1);
Mat re;
dtree->predict(trainingData_test,re);
cout<<calculateAccuracyPercent(classes_test,re)<<endl;
waitKey(0);
}