정보공간_1

[4기 강남 김태협] OpenCV 기계학습 알고리즘 소개 본문

IT 놀이터/Elite Member Tech & Talk

[4기 강남 김태협] OpenCV 기계학습 알고리즘 소개

알 수 없는 사용자 2013. 12. 4. 18:14

안녕하세요. 강남 멤버십 22-2기 김태협입니다.

이번에 소개드릴 내용은 OpenCV에 포함되어있는 기계학습(Machine Learning) 알고리즘에 관한 내용입니다.

 

1. OpenCV ML Library 소개

 

영상처리 분야에서 기계학습은 오랜 기간 동안 함께 연구되어 왔습니다. 카메라를 통해서 얻은 영상을 정제하고 가공하는 것이 영상처리라면 이를 분석하여 더욱 의미 있는 작업을 할 수 있도록 하는 것이 기계학습이라고 생각하시면 좋을 것 같습니다. 이처럼 기계학습은 영상처리를 통해 더욱 많은 일들을 할 수 있도록 하고 있습니다. 예를 들자면, 얼굴 인식, 보행자 인식, 최근에는 상황 인지 등을 예로 들 수 있습니다.

 

그 결과, OpenCV에서도 다음과 같은 기계학습 라이브러리를 공식 지원하고 있습니다.

 

1. Decision Tree

2. Support Vector Machine

3. Bayesian Classifier

4. Neural Networks

5. k-Nearest Neighbor

 

위 알고리즘은 기계학습 분야에서 대표적으로 사용되는 알고리즘입니다. 이미 많은 연구에서 검증되고 사용되고 있기 때문에, 각 각의 알고리즘 특성과 원리를 이해를 하셨다면 따로 구현하실 필요는 없습니다.

 

 

2. OpenCV ML Library 사용 예제

 

#include <iostream>

#include <opencv2/opencv.hpp>

 

#pragma comment(lib,"opencv_core242d.lib")

#pragma comment(lib,"opencv_highgui242d.lib")

#pragma comment(lib,"opencv_ml242d.lib")

 

using namespace cv;

using namespace std ;

bool plotSupportVectors = true ;

int numTrainingPoints = 200;

int numTestPoints = 2000;

int size = 200;

int eq = 0;

 

// 정확도 평가

float evaluate (Mat& predicted , Mat& actual ) {

        assert ( predicted.rows == actual.rows );

        int t = 0;

        int f = 0;

        for ( int i = 0; i < actual.rows ; i ++) {

               float p = predicted.at<float >(i ,0) ;

               float a = actual.at<float >(i ,0) ;

               if ((p >= 0.0&& a >= 0.0) || (p <= 0.0&& a <= 0.0) )

                       t ++;

               else

                       f ++;

        }

        return (t * 1.0) / (t + f);

}

// 차트 그리기

void plot_binary (Mat& data , Mat& classes , string name ) {

        Mat plot (size , size , CV_8UC3 );

        plot.setTo (Scalar (255.0 ,255.0 ,255.0) );

        for ( int i = 0; i < data.rows ; i ++) {

               float x = data.at<float >(i ,0) * size ;

               float y = data.at<float >(i ,1) * size ;

               if( classes.at<float >(i, 0) > 0)

                       circle (plot , Point (x,y), 2, CV_RGB (255 ,0 ,0) ,1);

               else

                       circle (plot , Point (x,y), 2, CV_RGB (0 ,255 ,0) ,1);

        }

        imshow (name , plot );

}

// 학습 데이터 생성

int f( float x, float y, int equation ) {

        switch ( equation ) {

        case 0:

               return y > sin (x *10) ? -1 : 1;

               break ;

        case 1:

               return y > cos (x * 10) ? -1 : 1;

               break ;

        case 2:

               return y > 2*x ? -1 : 1;

               break ;

        case 3:

               return y > tan (x *10) ? -1 : 1;

               break ;

        default :

               return y > cos (x *10) ? -1 : 1;

        }

} 

// 라벨 데이터

Mat labelData (Mat points , int equation ) {

        Mat labels ( points .rows , 1, CV_32FC1 );

        for ( int i = 0; i < points.rows ; i ++) {

               float x = points.at<float >(i ,0) ;

               float y = points.at<float >(i ,1) ;

               labels.at<float >(i, 0) = f(x, y, equation );

        }

        return labels ;

}

 

void svm (Mat& trainingData , Mat& trainingClasses , Mat& testData , Mat&  testClasses ) {

               CvSVMParams param = CvSVMParams();

               param.svm_type = CvSVM::C_SVC ;

               param.kernel_type = CvSVM::RBF;

               param.degree = 0;

               param.gamma = 20;

               param.coef0 = 0;

               param .C = 7;

               param .nu = 0.0;

               param .p = 0.0;

               param.class_weights = NULL ;

               param.term_crit.type = CV_TERMCRIT_ITER + CV_TERMCRIT_EPS ;

               param.term_crit.max_iter = 1000;

               param.term_crit.epsilon = 1e-6;

              

              

               CvSVM svm ( trainingData , trainingClasses , Mat() , Mat() , param );

               Mat predicted ( testClasses .rows , 1, CV_32F );

               for ( int i = 0; i < testData.rows ; i ++) {

                       Mat sample = testData .row(i);

                       float x = sample.at<float >(0 ,0) ;

                       float y = sample.at<float >(0 ,1) ;

                       predicted.at<float >(i, 0) = svm.predict ( sample );

               }

               cout << " Accuracy_ {SVM} = "

<< evaluate ( predicted , testClasses ) << endl ;

               plot_binary ( testData , predicted , " Predictions SVM ");

              

               if( plotSupportVectors ) {

                       Mat plot_sv (size , size , CV_8UC3 );

                       plot_sv.setTo (Scalar (255.0 ,255.0 ,255.0) );

                       int svec_count = svm.get_support_vector_count();

                       for ( int vecNum = 0; vecNum < svec_count ; vecNum ++) {

                              const float * vec = svm.get_support_vector ( vecNum );

                             circle ( plot_sv , Point ( vec [0]* size , vec [1]* size ),

                             3 , CV_RGB (0, 0, 0));

                       }

                       imshow (" Support Vectors ", plot_sv );

               }

}

 

void mlp (Mat& trainingData , Mat& trainingClasses , Mat& testData , Mat& testClasses )

{

               Mat layers = Mat (4, 1, CV_32SC1 );

               layers.row (0) = Scalar (2) ;

               layers.row (1) = Scalar (10) ;

               layers.row (2) = Scalar (15) ;

               layers.row (3) = Scalar (1) ;

 

               CvANN_MLP mlp ;

               CvANN_MLP_TrainParams params ;

               CvTermCriteria criteria ;

               criteria.max_iter = 100;

               criteria.epsilon = 0.00001f;

               criteria.type = CV_TERMCRIT_ITER | CV_TERMCRIT_EPS ;

               params.train_method = CvANN_MLP_TrainParams::BACKPROP ;

               params.bp_dw_scale = 0.05f;

               params.bp_moment_scale = 0.05f;

               params.term_crit = criteria ;

               mlp.create ( layers );

 

               mlp.train ( trainingData , trainingClasses , Mat() , Mat() , params );

               Mat response (1, 1, CV_32FC1 );

               Mat predicted ( testClasses .rows , 1, CV_32F );

               for ( int i = 0; i < testData.rows ; i ++) {

                       Mat response (1, 1, CV_32FC1 );

                       Mat sample = testData .row(i);

                       mlp.predict ( sample , response );

                       predicted.at<float >(i ,0) = response.at<float >(0 ,0) ;

               }

               cout << " Accuracy_ {MLP} = "

<< evaluate ( predicted , testClasses ) << endl ;

               plot_binary ( testData , predicted , " Predictions Backpropagation ");

}

 

void knn (Mat& trainingData , Mat& trainingClasses , Mat& testData , Mat testClasses , int K) {

               CvKNearest knn ( trainingData , trainingClasses , Mat() , false , K);

               Mat predicted ( testClasses .rows , 1, CV_32F );

               for ( int i = 0; i < testData.rows ; i ++) {

                       const Mat sample = testData.row (i);

                       predicted.at<float >(i ,0) = knn.find_nearest ( sample , K);

               }

               cout << " Accuracy_ {KNN} = "

    << evaluate ( predicted , testClasses ) << endl ;

               plot_binary ( testData , predicted , " Predictions KNN ");

}

 

void bayes (Mat& trainingData , Mat& trainingClasses , Mat& testData , Mat& testClasses ) {

               CvNormalBayesClassifier bayes ( trainingData , trainingClasses );

               Mat predicted ( testClasses .rows , 1, CV_32F );

               for (int i = 0; i < testData.rows ; i ++) {

                       const Mat sample = testData.row(i);

                       predicted.at<float > (i, 0) = bayes.predict ( sample );

               }

               cout << " Accuracy_ { BAYES } = "

    << evaluate ( predicted , testClasses ) << endl ;

               plot_binary ( testData , predicted , " Predictions Bayes ");

}

 

void decisiontree (Mat& trainingData , Mat& trainingClasses , Mat& testData ,

        Mat& testClasses ) {

               CvDTree dtree ;

 

               dtree.train ( trainingData , CV_ROW_SAMPLE , trainingClasses);

 

               Mat predicted ( testClasses .rows , 1, CV_32F );

               for (int i = 0; i < testData.rows ; i ++) {

                       const Mat sample = testData.row(i);

                       CvDTreeNode * prediction = dtree.predict ( sample );

                       predicted.at<float > (i, 0) = prediction -> value ;

               }

               cout << " Accuracy_ { TREE } = "

<< evaluate ( predicted , testClasses ) << endl ;

               plot_binary ( testData , predicted , " Predictions tree ");

}

 

int main() {

        Mat trainingData ( numTrainingPoints , 2, CV_32FC1 );

        Mat testData ( numTestPoints , 2, CV_32FC1 );

        randu ( trainingData ,0 ,1);

        randu ( testData ,0 ,1);

        Mat trainingClasses = labelData ( trainingData , eq);

        Mat testClasses = labelData ( testData , eq);

        plot_binary ( trainingData , trainingClasses , " Training Data ");

        plot_binary ( testData , testClasses , " Test Data ");

       

        // 기계 학습 알고리즘

        // Support Vector Machine

        // Neural Networks

        // k-Nearest Neighbor

        // Bayes Classifier

        // Decision Tree

        svm ( trainingData , trainingClasses , testData , testClasses );

        mlp ( trainingData , trainingClasses , testData , testClasses );

        knn ( trainingData , trainingClasses , testData , testClasses , 3);

        bayes ( trainingData , trainingClasses , testData , testClasses );

        decisiontree ( trainingData , trainingClasses , testData , testClasses );

 

        waitKey();

        return 0;

}

 

3. OpenCV ML Library 실험결과

다음 그림은 위 코드를 실행한 각 알고리즘의 실행 결과 입니다. 임의로 생성한 2차원 특징의 학습 데이터와 테스트 데이터를 이용하여 실험을 하였습니다.

 

 

이와 같은, 기계 학습을 알고리즘을 이용하면, 학습 데이터를 기반으로 새로운 입력에 대하여 예측을 할 수 있게 됩니다. 영상처리를 예로들면, 특정 오브젝트의 특징을 추출하여 특징벡터를 만들고 샘플링하여 위와 같은 방법을 통해 학습을 하면, 오브젝트를 인식을 할 수 있게 됩니다. (어떤 특징을 사용하느냐에 따라 성능이 달라지므로, 적합한 특징 추출이 중요합니다.)

 

지금 까지 OpenCV 포함 되어있는 기계학습 알고리즘과 그 사용방법을 함께 알아보았습니다. 여러 분들도 OpenCV의 기계학습 알고리즘을 사용하여 더 의미있는 결과를 만들어 보시기 바랍니다 :)

 

감사합니다.