openCV角點檢測


1,這章偷懶:

有個函數看不懂 

cornerEigenValsAndVecs()
作用:計算圖像塊的特征值和特征向量用於角點檢測。
形式:void cornerEigenValsAndVecs(InputArray src, OutputArray dst, int blockSize, int ksize, int borderType=BORDER_DEFAULT );
參數:
src:輸入單通道8位或浮點圖像;

dst:用來存儲結果的圖像;它有src相同的大小和類型為CV_32FC(6);

blockSize:領域尺寸;
ksize:Sobel()算子的孔徑參數;
borderType:像素外推方式;

輸出結果是:dst 圖像類型應該為CV_32FC(6),包含2個特征值,以及對應的2個2維向量,總計6個結果

類型六個數分別為(λ1,λ2,X1,Y1,X2,Y2) 

 

1.角點概述

     角點是圖像很重要的特征,對圖像圖形的理解和分析有很重要的作用。角點在保留圖像圖形重要特征的同時,可以有效地減少信息的數據量,使其信息的含量很高,

有效地提高了計算的速度,有利於圖像的可靠匹配,使得實時處理成為可能。角點在三維場景重建運動估計,目標跟蹤、目標識別、圖像配准與匹配等計算機視覺領域起着非常重要的作用。在現實世界中,角點對應於物體的拐角,道路的十字路口、丁字路口等。從圖像分析的角度來定義角點可以有以下兩種定義:

              a. 角點可以是兩個邊緣的角點;

              b. 角點是鄰域內具有兩個主方向的特征點;

     前者往往需要對圖像邊緣進行編碼,這在很大程度上依賴於圖像的分割與邊緣提取,具有相當大的難度和計算量,且一旦待檢測目標局部發生變化,很可能導致操作的失敗。

早期主要有Rosenfeld和Freeman等人的方法,后期有CSS等方法。基於圖像灰度的方法通過計算點的曲率及梯度來檢測角點,

避免了第一類方法存在的缺陷,此類方法主要有Moravec算子、Forstner算子、Harris算子、SUSAN算子等。本文主要介紹的Harris角點檢測的算法原理。

                                           

2. Harris角點檢測基本原理

      人眼對角點的識別通常是在一個局部的小區域或小窗口完成的。如果在各個方向上移動這個特征的小窗口,窗口內區域的灰度發生了較大的變化,那么就認為在窗口內遇到了角點。

如果這個特定的窗口在圖像各個方向上移動時,窗口內圖像的灰度沒有發生變化,那么窗口內就不存在角點;

如果窗口在某一個方向移動時,窗口內圖像的灰度發生了較大的變化,而在另一些方向上沒有發生變化,那么,窗口內的圖像可能就是一條直線的線段。如下圖:

                                           

          首先,將圖像窗口平移[u,v]產生灰度變化的自相關函數如下:

                                               

          其中窗口函數(權重矩陣)可以是平坦的,也可以是高斯的如下圖(權重矩陣W(通常為高斯濾波器Gσ):

                                                  

          

            然而將平移后的式子進行泰勒展開如下:

                               

            則:

                                 ,其中Ο(u2,v2)近似為0.故該式可以進一步簡化。

             由於是對局部微小的移動量 [u,v],所以可以近似得到下面忽略余項之后的表達式為一個二項式函數

                                    

                                                   

             其中,M的表達式如下,可由圖像的導數求得:

                             ,即M=W*MI,其中

              該卷積的目的是得到MI在周圍像素上的局部平均。矩陣M又稱為Harris矩陣。W 的寬度決定了在像素x 周圍的感興趣區域。

像這樣在區域附近對矩陣M取平均的原因是,特征值會依賴於局部圖像特性而變化。如果圖像的梯度在該區域變化,那么MI 的第二個特征值將不再為0。

如果圖像的梯度沒有變化,M的特征值也不會變化。

              忽略余項之后的表達式為一個二項式函數,然而二項式函數的本質上就是一個橢圓函數,橢圓的扁率和尺寸是由M(x,y)的特征值λ1、λ2決定的,

橢圓的方向是由M(x,y)的特征矢量決定的,如下圖所示,橢圓方程為:

                                                

 

    

     橢圓函數特征值與圖像中的角點、直線(邊緣)和平面之間的關系如下圖所示。共可分為三種情況:

           a. 圖像中的直線。一個特征值大,另一個特征值小,λ1>λ2或λ2>λ1。自相關函數值在某一方向上大,在其他方向上小。

           b. 圖像中的平面。兩個特征值都小,且近似相等;自相關函數數值在各個方向上都小。

           c. 圖像中的角點。兩個特征值都大,且近似相等,自相關函數在所有方向都增大。

     通過M的兩個特征值λ1和λ2的大小對圖像點進行分類:

                                                      

       如果λ1和λ2都很小,圖像窗口在所有方向上移動都無明顯灰度變化。

       由於我們是通過M的兩個特征值的大小對圖像進行分類,所以,定義角點相應函數R:

                                     

                                      

                                        

        

        其中k為經驗常數,一般取k=0.04~0.06。為了去除加權常數κ,我們通常使用商數detM/(traceM)2作為指示器。:所以,上圖可以轉化為:

                                                      

            

         其中:

               •  R 只與M的特征值有關

               • 角點:R 為大數值正數

               • 邊緣:R 為大數值負數

               • 平坦區:R 為小數值

         在判斷角點的時候,–對角點響應函數R進行閾值處理:R > threshold,提取R的局部極大值。

來自 :https://www.cnblogs.com/Jack-Elvis/p/11640931.html

代碼如下

cvtColor(src, gray_src, COLOR_BGR2GRAY);
    // 計算特征值
    int blockSize = 3;
    int ksize = 3;
    double k = 0.04;
    harris_dst = Mat::zeros(src.size(), CV_32FC(6));
    harrisRspImg = Mat::zeros(src.size(), CV_32FC1);
    qualityLevel = 30;
    max_count = 100;
    //計算圖像塊的特征值和特征向量用於角點檢測。
    cornerEigenValsAndVecs(gray_src, harris_dst, blockSize, ksize, 4);
    //cout << harris_dst << endl;

    // 計算響應
    for (int row = 0; row < harris_dst.rows; row++) {
        for (int col = 0; col < harris_dst.cols; col++) {
            double lambda1 = harris_dst.at<Vec6f>(row, col)[0];
            double lambda2 = harris_dst.at<Vec6f>(row, col)[1];
            //pow求次方
            harrisRspImg.at<float>(row, col) = lambda1*lambda2 - k*pow((lambda1 + lambda2), 2);
        }
    }
    minMaxLoc(harrisRspImg, &harris_min_rsp, &harris_max_rsp, 0, 0, Mat());
    namedWindow(harris_win, CV_WINDOW_AUTOSIZE);
    createTrackbar("Quality Value:", harris_win, &qualityLevel, max_count, CustomHarris_Demo);
    CustomHarris_Demo(0, 0);
void CustomHarris_Demo(int, void*) {
    if (qualityLevel < 20) {
        qualityLevel = 20;
    }
    Mat resultImg = src.clone();
    float t = harris_min_rsp + (((double)qualityLevel) / max_count)*(harris_max_rsp - harris_min_rsp);
    for (int row = 0; row < src.rows; row++) {
        for (int col = 0; col < src.cols; col++) {
            float v = harrisRspImg.at<float>(row, col);
            if (v > t) {
                circle(resultImg, Point(col, row), 2, Scalar(0, 0, 255), 2, 8, 0);
            }
        }
    }

    imshow(harris_win, resultImg);
}

自行參透,樓主不懂


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM