더북(TheBook)

digits.png 영상으로부터 HOG 특징 벡터를 추출하여 SVM 알고리즘으로 학습시키고, 사용자가 마우스로 쓴 필기체 숫자를 인식하는 svmdigits 예제 프로그램 소스 코드를 코드 15-6에 나타냈습니다. svmdigits 예제 프로그램은 15.2.3절에서 설명한 knndigits 예제 프로그램과 동작 방식이 거의 동일합니다. 다만 내부적으로 사용하는 머신 러닝 알고리즘과 머신 러닝에서 학습에 사용하는 특징 벡터 종류만 다를 뿐입니다. 코드 15-6의 svmdigits 전체 소스 코드 파일과 사용된 digits.png 영상 파일은 내려받은 예제 파일 중 ch15/svmdigits 프로젝트에서 확인하기 바랍니다.6

코드 15-6 SVM 알고리즘을 이용한 필기체 숫자 인식 [ch15/svmdigits]

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<SVM> train_hog_svm(const HOGDescriptor& hog);
09    void on_mouse(int event, int x, int y, int flags, void* userdata);
10     
11    int main()
12    {
13    #if _DEBUG
14        cout << "svmdigits.exe should be built as Release mode!" << endl;
15        return 0;
16    #endif
17     
18        HOGDescriptor hog(Size(20, 20), Size(10, 10), Size(5, 5), Size(5, 5), 9);
19     
20        Ptr<SVM> svm = train_hog_svm(hog);
21     
22        if (svm.empty()) {
23            cerr << "Training failed!" << endl;
24            return -1;
25        }
26     
27        Mat img = Mat::zeros(400, 400, CV_8U);
28     
29        imshow("img", img);
30        setMouseCallback("img", on_mouse, (void*)&img);
31     
32        while (true) {
33            int c = waitKey();
34     
35            if (c = = 27) {
36                break;
37            } else if (c = = ' ') {
38                Mat img_resize;
39                resize(img, img_resize, Size(20, 20), 0, 0, INTER_AREA);
40     
41                vector<float> desc;
42                hog.compute(img_resize, desc);
43     
44                Mat desc_mat(desc);
45                int res = cvRound(svm->predict(desc_mat.t()));
46                cout << res << endl;
47     
48                img.setTo(0);
49                imshow("img", img);
50            }
51        }
52     
53        return 0;
54    }
55     
56    Ptr<SVM> train_hog_svm(const HOGDescriptor& hog)
57    {
58        Mat digits = imread("digits.png", IMREAD_GRAYSCALE);
59     
60        if (digits.empty()) {
61            cerr << "Image load failed!" << endl;
62            return 0;
63        }
64     
65        Mat train_hog, train_labels;
66     
67        for (int j = 0; j < 50; j++) {
68            for (int i = 0; i < 100; i++) {
69                Mat roi = digits(Rect(i * 20, j * 20, 20, 20));
70     
71                vector<float> desc;
72                hog.compute(roi, desc);
73     
74                Mat desc_mat(desc);
75                train_hog.push_back(desc_mat.t());
76                train_labels.push_back(j / 5);
77            }
78        }
79     
80        Ptr<SVM> svm = SVM::create();
81        svm->setType(SVM::Types::C_SVC);
82        svm->setKernel(SVM::KernelTypes::RBF);
83        svm->setC(2.5);
84        svm->setGamma(0.50625);
85        svm->train(train_hog, ROW_SAMPLE, train_labels);
86     
87        return svm;
88    }
89     
90    Point ptPrev(-1, -1);
91     
92    void on_mouse(int event, int x, int y, int flags, void* userdata)
93    {
94        Mat img = *(Mat*)userdata;
95     
96        if (event = = EVENT_LBUTTONDOWN)
97            ptPrev = Point(x, y);
98        else if (event = = EVENT_LBUTTONUP)
99            ptPrev = Point(-1, -1);
100       else if (event = = EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON))
101       {
102           line(img, ptPrev, Point(x, y), Scalar::all(255), 40, LINE_AA, 0);
103           ptPrev = Point(x, y);
104    
105           imshow("img", img);
106       }
107   }

 

 

6 svmdigits 프로그램은 HOGDescriptor 클래스 구현상의 문제로 디버그 모드에서는 동작하지 않고 릴리스 모드에서만 동작합니다. 그러므로 Visual Studio 상단 솔루션 구성을 Release로 변경한 후 실행하기 바랍니다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.