Use opencv to train a handwritten number recognition classifier
1. Download the training data and test data files. Here the mnist handwritten digital image library is used, of which 60000 are training databases and 10000 are Test Databases.
2. Create a function to read training data and test data files. Note that the byte sequence is large.
3. determine the character feature mode as the simplest number of characters in the 8 × 8 Grid
4. Create an SVM, train and read the SVM. The result is as follows:
1000 training samples with a testing data accuracy rate of 80.21% (not reflecting the high accuracy of SVM samples)
10000 training samples with a testing data accuracy rate of 95.45%
60000 training samples with a testing data accuracy rate of 97.67%
5. Write and verify the GUI program written by hand. The results are acceptable.
The following is the main code for your reference:
(Similarly, a random tree classifier is implemented, and the SVM accuracy is slightly higher when the number of samples is the same)
# Include "stdafx. H "</P> <p> # include <fstream> <br/> # include" opencv2/opencv. HPP "<br/> # include <vector> </P> <p> using namespace STD; <br/> using namespace CV; </P> <p> # define show_process 0 <br/> # define on_study 0 </P> <p> class numtraindata <br/> {<br/> public: <br/> numtraindata () <br/> {<br/> memset (data, 0, sizeof (data); <br/> result =-1; <br/>}< br/> Public: <br/> float data [64]; <br/> int result; <br/>}; </ P> <p> vector <numtraindata> buffer; <br/> int featurelen = 64; </P> <p> void swapbuffer (char * BUF) <br/>{< br/> char temp; <br/> temp = * (BUF); <br/> * Buf = * (BUF + 3 ); <br/> * (BUF + 3) = temp; </P> <p> temp = * (BUF + 1); <br/> * (BUF + 1) = * (BUF + 2); <br/> * (BUF + 2) = temp; <br/>}</P> <p> void getroi (MAT & SRC, mat & DST) <br/>{< br/> int left, right, top, bottom; <br/> left = SRC. cols; <br/> right = 0; <br/> Top = SRC. rows; <br /> Bottom = 0; </P> <p> // get valid area <br/> for (INT I = 0; I <SRC. rows; I ++) <br/>{< br/> for (Int J = 0; j <SRC. cols; j ++) <br/>{< br/> If (SRC. at <uchar> (I, j)> 0) <br/>{< br/> If (j <left) Left = J; <br/> If (j> right) Right = J; <br/> if (I <top) Top = I; <br/> if (I> bottom) bottom = I; <br/>}</P> <p> // point center; <br/> // center. X = (left + right)/2; <br/> // center. y = (top + bottom)/2; </P> <p> int wi DTH = right-left; <br/> int Height = bottom-top; <br/> int Len = (width <peight )? Height: width; </P> <p> // create a squre <br/> DST = mat: zeros (Len, Len, cv_8uc1 ); </P> <p> // copy valid data to squre center <br/> rect dstrect (LEN-width)/2, (LEN-height)/2, width, height); <br/> rect srcrect (left, top, width, height); <br/> mat dstroi = DST (dstrect ); <br/> mat srcroi = SRC (srcrect); <br/> srcroi. copyto (dstroi); <br/>}</P> <p> int readtraindata (INT maxcount) <br/>{< br/> // open image and Label file <br/> const char filename [] = ".. /RES/train-images.idx3-ubyte "; <br/> const char labelfilename [] = ".. /RES/train-labels.idx1-ubyte "; </P> <p> ifstream lab_ifs (labelfilename, ios_base: Binary); <br/> ifstream ifs (filename, ios_base: Binary ); </P> <p> If (IFS. fail () = true) <br/> return-1; </P> <p> If (lab_ifs.fail () = true) <br/> return-1; </P> <p> // read train data number and image rows/Cols <br /> Char magicnum [4], ccount [4], crows [4], ccols [4]; <br/> ifs. read (magicnum, sizeof (magicnum); <br/> ifs. read (ccount, sizeof (ccount); <br/> ifs. read (crows, sizeof (CROWS); <br/> ifs. read (ccols, sizeof (ccols); </P> <p> int count, rows, cols; <br/> swapbuffer (ccount ); <br/> swapbuffer (CROWS); <br/> swapbuffer (ccols); </P> <p> memcpy (& count, ccount, sizeof (count )); <br/> memcpy (& rows, crows, sizeof (rows); <br/> Memcpy (& cols, ccols, sizeof (Cols); </P> <p> // just skip label header <br/> lab_ifs.read (magicnum, sizeof (magicnum); <br/> lab_ifs.read (ccount, sizeof (ccount )); </P> <p> // create source and show image matrix <br/> mat src = mat: zeros (rows, cols, cv_8uc1 ); <br/> mat temp = mat: zeros (8, 8, cv_8uc1); <br/> mat IMG, DST; </P> <p> char label = 0; <br/> scalar templatecolor (255, 0,255); </P> <p> numtraindata RTD; </ P> <p> // int loop = 1000; <br/> int Total = 0; </P> <p> while (! IFS. EOF () <br/>{< br/> If (total> = count) <br/> break; </P> <p> total ++; <br/> cout <total <Endl; </P> <p> // read label <br/> lab_ifs.read (& label, 1 ); <br/> label = label + '0'; </P> <p> // read source data <br/> ifs. read (char *) SRC. data, rows * Cols); <br/> getroi (SRC, DST); </P> <p> # If (show_process) <br/> // too small to watch <br/> IMG = mat: zeros (DST. rows * 10, DST. cols * 10, cv_8uc1); <br/> resize (DST, IMG, IMG. size (); </P> <p> stringstream SS; <br/> SS <"Number" <label; <br/> string text = ss. STR (); <br/> puttext (IMG, text, point (10, 50), font_hershey_simplex, 1.0, templatecolor ); </P> <p> // imshow ("IMG", IMG); <br/> # endif </P> <p> RTD. result = label; <br/> resize (DST, temp, temp. size (); <br/> // threshold (temp, temp, 10, 1, cv_thresh_binary); </P> <p> for (INT I = 0; I <8; I ++) <br/> {<br/> for (Int J = 0; j <8; j ++) <br/>{< br/> RTD. data [I * 8 + J] = temp. at <uchar> (I, j); <br/>}</P> <p> buffer. push_back (RTD); </P> <p> // If (waitkey (0) = 27) // ESC to quit <br/> // break; </P> <p> maxcount --; </P> <p> If (maxcount = 0) <br/> break; <br/>}</P> <p> ifs. close (); <br/> lab_ifs.close (); </P> <p> return 0; <br/>}</P> <p> void newrtstudy (vector <numtraindata> & traindata) <br/>{< br/> int testcount = traindata. size (); </P> <p> mat DATA = mat: zeros (testcount, featurelen, cv_32fc1); <br/> mat res = mat: zeros (testcount, 1, cv_32sc1); </P> <p> for (INT I = 0; I <testcount; I ++) <br/>{</P> <p> numtraindata TD = traindata. at (I); <br/> memcpy (data. data + I * featurelen * sizeof (float), TD. data, featurelen * sizeof (float); </P> <p> res. at <unsigned int> (I, 0) = TD. result; <br/>}</P> <p> // start RT trainning //////////// ////// <br/> cvrtrees forest; <br/> cvmat * var_importance = 0; </P> <p> forest. train (data, cv_row_sample, res, MAT (), <br/> cvrtparams (10, 10, 0, false, 15, 0, true, 4,100, 0.01f, cv_termcrit_iter); <br/> forest. save ("new_rtrees.xml"); <br/>}</P> <p> int newrtpredict () <br/>{< br/> cvrtrees forest; <br/> forest. load ("new_rtrees.xml"); </P> <p> const char filename [] = ".. /RES/t10k-images.idx3-ubyte "; <br/> const char labelfilename [] = ".. /RES/t10k-labels.idx1-ubyte "; </P> <p> ifstream lab_ifs (labelfilename, ios_base: Binary); <br/> ifstream ifs (filename, ios_base: Binary ); </P> <p> If (IFS. fail () = true) <br/> return-1; </P> <p> If (lab_ifs.fail () = true) <br/> return-1; </P> <p> char magicnum [4], ccount [4], crows [4], ccols [4]; <br/> ifs. read (magicnum, sizeof (magicnum); <br/> ifs. read (ccount, sizeof (ccount); <br/> ifs. read (crows, sizeof (CROWS); <br/> ifs. read (ccols, sizeof (ccols); </P> <p> int count, rows, cols; <br/> swapbuffer (ccount ); <br/> swapbuffer (CROWS); <br/> swapbuffer (ccols); </P> <p> memcpy (& count, ccount, sizeof (count )); <br/> memcpy (& rows, crows, sizeof (rows); <br/> memcpy (& cols, ccols, sizeof (Cols )); </P> <p> mat src = mat: zeros (rows, cols, cv_8uc1); <br/> mat temp = mat: zeros (8, 8, cv_8uc1); <br/> mat M = mat: zeros (1, featurelen, cv_32fc1); <br/> mat IMG, DST; </P> <p> // just skip label header <br/> lab_ifs.read (magicnum, sizeof (magicnum); <br/> lab_ifs.read (ccount, sizeof (ccount); </P> <p> char label = 0; <br/> scalar templatecolor (255, 0, 0 ); </P> <p> numtraindata RTD; </P> <p> int right = 0, error = 0, total = 0; <br/> int right_1 = 0, error_1 = 0, right_2 = 0, error_2 = 0; <br/> while (IFS. good () <br/>{< br/> // read label <br/> lab_ifs.read (& label, 1 ); <br/> label = label + '0'; </P> <p> // read data <br/> ifs. read (char *) SRC. data, rows * Cols); <br/> getroi (SRC, DST); </P> <p> // too small to watch <br/> IMG = mat :: zeros (DST. rows * 30, DST. cols * 30, cv_8uc3); <br/> resize (DST, IMG, IMG. size (); </P> <p> RTD. result = label; <br/> resize (DST, temp, temp. size (); <br/> // threshold (temp, temp, 10, 1, cv_thresh_binary); <br/> for (INT I = 0; I <8; I ++) <br/>{< br/> for (Int J = 0; j <8; j ++) <br/>{< br/> M. at <float> (0, J + I * 8) = temp. at <uchar> (I, j); <br/>}</P> <p> If (total> = count) <br/> break; </P> <p> char ret = (char) Forest. predict (m); </P> <p> If (ret = label) <br/>{< br/> right ++; <br/> If (total <= 5000) <br/> right_1 ++; <br/> else <br/> right_2 ++; <br/>}< br/> else <br/>{< br/> error ++; <br/> If (total <= 5000) <br/> error_1 ++; <br/> else <br/> error_2 ++; <br/>}</P> <p> total ++; </P> <p> # If (show_process) <br/> stringstream SS; <br/> SS <"Number" <label <", predict "<ret; <br/> string text = ss. STR (); <br/> puttext (IMG, text, point (10, 50), font_hershey_simplex, 1.0, templatecolor ); </P> <p> imshow ("IMG", IMG); <br/> If (waitkey (0) = 27) // ESC to quit <br/> break; <br/> # endif </P> <p >}</P> <p> ifs. close (); <br/> lab_ifs.close (); </P> <p> stringstream SS; <br/> SS <"Total" <total <", right "<right <", error "<error; <br/> string text = ss. STR (); <br/> puttext (IMG, text, point (50, 50), font_hershey_simplex, 1.0, templatecolor); <br/> imshow ("IMG ", IMG); <br/> waitkey (0); </P> <p> return 0; <br/>}</P> <p> void newsvmstudy (vector <numtraindata> & traindata) <br/>{< br/> int testcount = traindata. size (); </P> <p> mat M = mat: zeros (1, featurelen, cv_32fc1); <br/> mat DATA = mat: zeros (testcount, featurelen, cv_32fc1); <br/> mat res = mat: zeros (testcount, 1, cv_32sc1); </P> <p> for (INT I = 0; I <testcount; I ++) <br/>{</P> <p> numtraindata TD = traindata. at (I); <br/> memcpy (M. data, TD. data, featurelen * sizeof (float); <br/> normalize (M, m); <br/> memcpy (data. data + I * featurelen * sizeof (float), M. data, featurelen * sizeof (float); </P> <p> res. at <unsigned int> (I, 0) = TD. result; <br/>}</P> <p> // start SVM trainning //////////// ///// <br/> cvsvm = cvsvm (); <br/> cvsvmparams Param; <br/> cvtermcriteria criteria; </P> <p> Criteria = cvtermcriteria (cv_termcrit_eps, 1000, flt_epsilon ); <br/> param = cvsvmparams (cvsvm: c_svc, cvsvm: RBF, 10.0, 8.0, 1.0, 10.0, 0.5, null, criteria ); </P> <p> SVM. train (data, res, MAT (), MAT (), Param); <br/> SVM. save ("svm_data.xml"); <br/>}</P> <p> int newsvmpredict () <br/>{< br/> cvsvm = cvsvm (); <br/> SVM. load ("svm_data.xml"); </P> <p> const char filename [] = ".. /RES/t10k-images.idx3-ubyte "; <br/> const char labelfilename [] = ".. /RES/t10k-labels.idx1-ubyte "; </P> <p> ifstream lab_ifs (labelfilename, ios_base: Binary); <br/> ifstream ifs (filename, ios_base: Binary ); </P> <p> If (IFS. fail () = true) <br/> return-1; </P> <p> If (lab_ifs.fail () = true) <br/> return-1; </P> <p> char magicnum [4], ccount [4], crows [4], ccols [4]; <br/> ifs. read (magicnum, sizeof (magicnum); <br/> ifs. read (ccount, sizeof (ccount); <br/> ifs. read (crows, sizeof (CROWS); <br/> ifs. read (ccols, sizeof (ccols); </P> <p> int count, rows, cols; <br/> swapbuffer (ccount ); <br/> swapbuffer (CROWS); <br/> swapbuffer (ccols); </P> <p> memcpy (& count, ccount, sizeof (count )); <br/> memcpy (& rows, crows, sizeof (rows); <br/> memcpy (& cols, ccols, sizeof (Cols )); </P> <p> mat src = mat: zeros (rows, cols, cv_8uc1); <br/> mat temp = mat: zeros (8, 8, cv_8uc1); <br/> mat M = mat: zeros (1, featurelen, cv_32fc1); <br/> mat IMG, DST; </P> <p> // just skip label header <br/> lab_ifs.read (magicnum, sizeof (magicnum); <br/> lab_ifs.read (ccount, sizeof (ccount); </P> <p> char label = 0; <br/> scalar templatecolor (255, 0, 0 ); </P> <p> numtraindata RTD; </P> <p> int right = 0, error = 0, total = 0; <br/> int right_1 = 0, error_1 = 0, right_2 = 0, error_2 = 0; <br/> while (IFS. good () <br/>{< br/> // read label <br/> lab_ifs.read (& label, 1 ); <br/> label = label + '0'; </P> <p> // read data <br/> ifs. read (char *) SRC. data, rows * Cols); <br/> getroi (SRC, DST); </P> <p> // too small to watch <br/> IMG = mat :: zeros (DST. rows * 30, DST. cols * 30, cv_8uc3); <br/> resize (DST, IMG, IMG. size (); </P> <p> RTD. result = label; <br/> resize (DST, temp, temp. size (); <br/> // threshold (temp, temp, 10, 1, cv_thresh_binary); <br/> for (INT I = 0; I <8; I ++) <br/>{< br/> for (Int J = 0; j <8; j ++) <br/>{< br/> M. at <float> (0, J + I * 8) = temp. at <uchar> (I, j); <br/>}</P> <p> If (total> = count) <br/> break; </P> <p> normalize (M, m); <br/> char ret = (char) SVM. predict (m); </P> <p> If (ret = label) <br/>{< br/> right ++; <br/> If (total <= 5000) <br/> right_1 ++; <br/> else <br/> right_2 ++; <br/>}< br/> else <br/>{< br/> error ++; <br/> If (total <= 5000) <br/> error_1 ++; <br/> else <br/> error_2 ++; <br/>}</P> <p> total ++; </P> <p> # If (show_process) <br/> stringstream SS; <br/> SS <"Number" <label <", predict "<ret; <br/> string text = ss. STR (); <br/> puttext (IMG, text, point (10, 50), font_hershey_simplex, 1.0, templatecolor ); </P> <p> imshow ("IMG", IMG); <br/> If (waitkey (0) = 27) // ESC to quit <br/> break; <br/> # endif </P> <p >}</P> <p> ifs. close (); <br/> lab_ifs.close (); </P> <p> stringstream SS; <br/> SS <"Total" <total <", right "<right <", error "<error; <br/> string text = ss. STR (); <br/> puttext (IMG, text, point (50, 50), font_hershey_simplex, 1.0, templatecolor); <br/> imshow ("IMG ", IMG); <br/> waitkey (0); </P> <p> return 0; <br/>}</P> <p> int main (INT argc, char * argv []) <br/>{< br/> # If (on_study) <br/> int maxcount = 60000; <br/> readtraindata (maxcount ); </P> <p> // newrtstudy (buffer); <br/> newsvmstudy (buffer); <br/> # else <br/> // newrtpredict (); <br/> newsvmpredict (); <br/> # endif <br/> return 0; <br/>}