2009年10月28日 星期三

[技術] 使用 OpenCV 進行 KNN 分類最簡單範例

snap003

 

工作是這樣的, 我們希望學習到下面的事情:

      A. 產生最簡單的兩個 normal distribution 分佈 training sets 
      B. 丟給 KNN 學習
      C. 放 sample data 給 KNN, 進行預測

 

這裡有幾個關鍵:

如何產生 training data

// Step 0: 建立 100 組 (x,y) 資料的陣列 與 存放標準答案的陣列
int train_sample_count=100;
CvMat* trainData = cvCreateMat(train_sample_count,2,CV_32FC1); 
CvMat* trainClasses = cvCreateMat( train_sample_count, 1,
                                                                           CV_32FC1 ); 
CvRNG rng_state = cvRNG(-1); // 亂數產生器: 產生 normalization 使用

 

// Step 1: 第一筆資料
//        陣列 index 0 - 99 的地方, 放training set 數值
//        分佈型態  normal distribution,
//                           mean value=(200,200), Variance=(50,50)
    CvMat trainData1;
    cvGetRows( trainData, &trainData1, 0, train_sample_count/2 );          
    cvRandArr( &rng_state, &trainData1, CV_RAND_NORMAL,
                              cvScalar(200,200), cvScalar(50,50));

 

// Step 2: 指定第一筆資料全部屬於類別 1
    CvMat trainClasses1;
    cvGetRows(trainClasses, &trainClasses1, 0, train_sample_count/2 ); 
    cvSet( &trainClasses1, cvScalar(1));

 

如何把 training set 丟給 KNN 物件學習?

// Step 1: 建立 KNN 物件
    int K=10;
    CvKNearest knn( trainData, trainClasses, 0, false, K );

 

如何對一個 testing sample 進行分類?

// Step 1: 進行 KNN 的預測

            // a. 設定 testing sample 的值
            sample.data.fl[0] = (float)j;
            sample.data.fl[1] = (float)i;

           // [關鍵片段]
            // b. 利用 KNN 演算法取得最近的 K 個 samples. ex:[0,1,0,...,1]
            //      return the nearest class

            float response = knn.find_nearest(&sample,K,0,0,nearests,0);

            // c. KNN 預測的結果與標準答案的比較
            for(k = 0, accuracy = 0; k < K; k++ ){
                if( nearests->data.fl[k] == response)
                    accuracy++; // 計算 K 個最接近的 label, 符合標準答案的數量
            }

            // d. 若預測結果正確的數值超過一半, 則使用紅色/綠色表示
            //    否則使用橘色表示
            cvSet2D( img, i, j, response == 1 ?
                (accuracy > 5 ? CV_RGB(180,0,0) : CV_RGB(180,120,0)) :
                (accuracy > 5 ? CV_RGB(0,180,0) : CV_RGB(120,120,0)) );
        }

 

現在你可以看完整的範例了. [View]

 

Enjoy.

by Jing.