Artificial Neural Networks && FileStorage of OpenCV

1. 文檔簡單介紹

參考【opencv2refman.pdf】



ANN原理及響應函數設置如上所述;

ANN與其他分類算法有一個不同點是,構建和訓練分開進行;

2.OpenCV實現代碼

2.1//XML文件載入訓練數據和類別標籤,並進行訓練;

OCR::OCR(string trainFile){
    DEBUG=false;
    trained=false;
    saveSegments=false;
	//字符塊的寬高
    charSize=20;

    //Read file storage.
    FileStorage fs;
    fs.open("OCR.xml", FileStorage::READ);
	//新建兩個矩陣,用於存儲訓練數據和類別標籤;
    Mat TrainingData;
    Mat Classes;
    fs["TrainingDataF15"] >> TrainingData;
    fs["classes"] >> Classes;
	//10層ANN,訓練
    train(TrainingData, Classes, 10);

}

2.2訓練

void OCR::train(Mat TrainData, Mat classes, int nlayers){
	//矩陣,用於創建ANN;1行3列;訓練數據的列數(特徵屬性),ANN的層數,字符數(類別標籤);
    Mat layers(1,3,CV_32SC1);
    layers.at<int>(0)= TrainData.cols;
    layers.at<int>(1)= nlayers;
    layers.at<int>(2)= numCharacters;
	//使用sigmoid創建ANN
    ann.create(layers, CvANN_MLP::SIGMOID_SYM, 1, 1);

    //Prepare trainClases
    //Create a mat with n trained data by m classes
    Mat trainClasses;
	//TrainData.rows表示訓練數據的數量;
    trainClasses.create( TrainData.rows, numCharacters, CV_32FC1 );
    for( int i = 0; i <  trainClasses.rows; i++ )
    {
        for( int k = 0; k < trainClasses.cols; k++ )
        {
            //If class of data i is same than a k class
			//trainClasses的第i個row存儲第i個樣本的標籤類別,而此標籤存儲在class的第i個元素下;
			//class(numCharacters)-->trainClasses(TrainData.rows, numCharacters)矩陣轉換;
			//(i,j),遍歷j;在樣本i對應標籤位置置爲1;
			//比如第5個樣本對應第3個類別,則設置trainClasses(5,3)=1;
            if( k == classes.at<int>(i) )
                trainClasses.at<float>(i,k) = 1;
            else
                trainClasses.at<float>(i,k) = 0;
        }
    }
	//所有的訓練樣本權重都爲1;
    Mat weights( 1, TrainData.rows, CV_32FC1, Scalar::all(1) );
	if (DEBUG)
	{
		//存儲訓練前的類別標籤;
		FileStorage classBefore;
		classBefore.open("classBefore.xml", FileStorage::WRITE);
		classBefore << "before" << trainClasses;
		classBefore.release();
	}
    //Learn classifier,訓練數據,類別標籤(大矩陣形式),權重;
	//類別標籤並不會變化,此API僅訓練ANN;
    ann.train( TrainData, trainClasses, weights );
	if (DEBUG)
	{
		//存儲訓練後的類別標籤;
		FileStorage classAfter;
		classAfter.open("classAfter.xml", FileStorage::WRITE);
		classAfter << "after" << trainClasses;
		classAfter.release();
	}
    trained=true;
}

2.3 分類測試

ann.predict(f, output);

2.4 錯誤備註

在進行LED數字識別項目時,使用ANN和KNN對比,當然還是ANN的效果更好些;出現一些需要強調的錯誤:

2.4.1 訓練類別需要使用整型 int

//set the class of train feature;
	vector<int> numberLabel;
	for (int colsIdx = 0; colsIdx<10; ++colsIdx)
	<span style="white-space:pre">	</span>numberLabel.push_back(colsIdx);
	Mat(numberLabel).copyTo(ftrClass);
按上述方式新建類別矩陣;

2.4.2 矩陣copy時類型準確
for (int rowsIdx = 0, toFtrIdx = 0; rowsIdx < tempFtr.rows; ++rowsIdx)
	for (int colsIdx = 0; colsIdx < tempFtr.cols; ++colsIdx, ++toFtrIdx)
		ftrNumberTa.at<float>(nuIdex, toFtrIdx) = tempFtr.at<float>(rowsIdx, colsIdx);

矩陣copy取值時,一般將rows作爲第一層,cols作爲第二層;
也可不強制按照此模式,理解
MatName.at<dataType>(rowsIdx,colsIdx);
另外Mat新建
//cols即image的寬;rows即image的高
	Mat ftrNumberTa(cv::Size(ftrNumber_cols, ftrNumber_rows), CV_32F);

此文僅簡單記載ANN識別在opencv中的使用流程;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章