knndigits 예제 프로그램의 main() 함수는 코드 15-4에 나타냈습니다. main() 함수에서는 먼저 필기체 숫자 영상 데이터를 학습하는 train_knn() 함수를 호출하고, 사용자가 영상 위에 글씨를 쓸 수 있게끔 마우스 콜백 함수를 등록하는 setMouseCallback() 함수를 호출합니다. 그리고 키보드 입력을 확인하여 사용자가 Space 키를 누를 때마다 사용자가 그린 글씨를 인식하여 콘솔 창에 출력합니다. 코드 15-2부터 코드 15-4까지 소개된 knndigits 전체 소스 코드 파일과 사용된 digits.png 영상 파일은 내려받은 예제 파일 중 ch15/knndigits 프로젝트에서 확인할 수 있습니다.
코드 15-4 KNearest 클래스를 이용한 필기체 숫자 인식 [ch15/knndigits]
01 #include "opencv2/opencv.hpp" 02 #include <iostream> 03 04 using namespace cv; 05 using namespace cv::ml; 06 using namespace std; 07 08 Ptr<KNearest> train_knn(); 09 void on_mouse(int event, int x, int y, int flags, void* userdata); 10 11 int main() 12 { 13 Ptr<KNearest> knn = train_knn(); 14 15 if (knn.empty()) { 16 cerr << "Training failed!" << endl; 17 return -1; 18 } 19 20 Mat img = Mat::zeros(400, 400, CV_8U); 21 22 imshow("img", img); 23 setMouseCallback("img", on_mouse, (void*)&img); 24 25 while (true) { 26 int c = waitKey(0); 27 28 if (c = = 27) { 29 break; 30 } else if (c = = ' ') { 31 Mat img_resize, img_float, img_flatten, res; 32 33 resize(img, img_resize, Size(20, 20), 0, 0, INTER_AREA); 34 img_resize.convertTo(img_float, CV_32F); 35 img_flatten = img_float.reshape(1, 1); 36 37 knn->findNearest(img_flatten, 3, res); 38 cout << cvRound(res.at<float>(0, 0)) << endl; 39 40 img.setTo(0); 41 imshow("img", img); 42 } 43 } 44 45 return 0; 46 }