1. 程式人生 > >opencv——基於SVM的數字識別(3)

opencv——基於SVM的數字識別(3)

前兩篇文章寫了基於兩種特徵提取的SVM數字識別

https://blog.csdn.net/weixin_41721222/article/details/84953788

https://blog.csdn.net/weixin_41721222/article/details/84978343

這篇文章主要是關於模型評估,即識別數字的正確率

 

下面程式碼是opencv3  c++

載入的XML檔案是之前程式碼訓練好的。

測試集是我的“”數字檢測樣本“”資料夾下的0-9個資料夾所包含的檢測樣本

 

 


#include <stdio.h>  
#include <time.h>  
#include <opencv2/opencv.hpp>  
#include <opencv/cv.h>  
#include <iostream> 
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/ml/ml.hpp>  
#include <io.h> //查詢檔案相關函式


using namespace std;
using namespace cv;
using namespace ml;
ostringstream oss;
Mat dealimage;
int num = -1;
Mat yangben_gray;
Mat yangben_thresh;
void shibie(Mat dealimage);
int yangben_data_position = 0;//代表為第幾幅影象
int right_lei = -1;//讓後面評估模型判斷是否分類正確
int rigth_number = 0;//分類正確的個數
int test_num = 0;//累計總共的測試影象個數
Ptr<SVM>SVM_params;
int main()
{
	//載入XML檔案
	SVM_params = SVM::load("C:/Users/zhang/Desktop/opencv——例項/小案例/車牌檢測/基於機器學習/字元識別svm.xml");
	const int classsum = 10;//圖片共有10類
	//////////////////////從指定資料夾下提取圖片//////////////////
	for (int p = 0; p < classsum; p++)
	{
		right_lei += 1;//讓後面評估模型判斷是否分類正確
		oss << "C:/Users/zhang/Desktop/opencv——例項/機器學習/數字檢測樣本/";
		num += 1;//num從0到9
		int label = num;
		oss << num << "/*.jpg";//圖片名字字尾,oss可以結合數字與字串
		string pattern = oss.str();//oss.str()輸出oss字串,並且賦給pattern
		oss.str("");//每次迴圈後把oss字串清空
		vector<Mat> input_images;
		vector<String> input_images_name;
		glob(pattern, input_images_name, false);
		//為false時,僅僅遍歷指定資料夾內符合模式的檔案,當為true時,會同時遍歷指定資料夾的子資料夾
		//此時input_images_name存放符合條件的圖片地址
		int all_num = input_images_name.size();//檔案下總共有幾個圖片
		//cout << num << ":總共有" << all_num << "個圖片待測試" << endl;

		for (int i = 0; i < all_num; i++)
		{
			cvtColor(imread(input_images_name[i]), yangben_gray, COLOR_BGR2GRAY);
			threshold(yangben_gray, yangben_thresh, 0, 255, THRESH_OTSU);
			input_images.push_back(yangben_thresh);
			//迴圈讀取每張圖片並且依次放在vector<Mat> input_images內
			dealimage = input_images[i];
			yangben_data_position += 1;//代表為第幾幅影象
			test_num += 1;//累計總共的測試影象
			cout << "正在識別第" << yangben_data_position << "張圖片" << endl;
			shibie(dealimage);
	
		}
	}

	//模型評估//
	cout << "正確個數"<<rigth_number << endl <<"總檢測個數"<< test_num << endl;
	double right_rate = double(rigth_number) / double(test_num);
	cout << "正確率為:" << right_rate << endl;


	waitKey(0);
	return 0;
}
void shibie(Mat dealimage)
{
	//imshow("原影象", gray);
	//輸入影象取特徵點
	Mat trainTempImg = Mat::zeros(Size(128, 128), CV_8UC1);
	resize(dealimage, trainTempImg, trainTempImg.size());

	HOGDescriptor *hog = new HOGDescriptor(Size(128, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9);
	vector<float>descriptors;//結果陣列         
	hog->compute(trainTempImg, descriptors, Size(1, 1), Size(0, 0));
	//cout << "HOG描述子向量維數    " << descriptors.size() << endl;
	Mat SVMtrainMat = Mat(1, descriptors.size(), CV_32FC1);

	int  number1 = descriptors.size();
	//將計算好的HOG描述子複製到樣本特徵矩陣SVMtrainMat  
	for (int i = 0; i < number1; i++)
	{
		//把一幅影象的HOG描述子向量依次存入data_mat矩陣的同一列
		//因為輸入影象只有一個,即SVMtrainMat只有一列,則為0
		SVMtrainMat.at<float>(0, i) = descriptors[i];  									  //  n++;
	}

	SVMtrainMat.convertTo(SVMtrainMat, CV_32FC1);//更改圖片資料的型別,必要,不然會出錯
	int ret = (int)SVM_params->predict(SVMtrainMat);//檢測結果  
	cout << "識別的數字為:" << ret << "\t";

	if (right_lei == ret)
	{
		cout << "識別正確" << endl;
		rigth_number+=1;
	}
	if (right_lei != ret)
		cout << "識別錯誤" << "\t" << "正確值為:" << right_lei << endl;
}

 

 

結果:

 

正確率為百分之67,不高主要是因為訓練集用的是手寫數字。而測試集用的是車牌數字。