1. 程式人生 > >OPENCV的學習:影象特徵檢測之Harris角點演算法

OPENCV的學習:影象特徵檢測之Harris角點演算法

    影象檢測是影象分割,影象識別的基礎,也是不可缺少的關鍵。在視覺計算理論框架中,抽取二維影象的邊緣、角點、紋理等基本特徵,是整個框架的第一步;本文章對Harris角點演算法做了比較詳細的理論介紹以及相關實現。

Part One:角點型別介紹

在現實世界中,角點對應於物體的拐角,道路的十字路口、丁字路口等。從影象分析的角度來定義角點可以有以下兩種定義:

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

                  角點是鄰域內具有兩個主方向的特徵點                                                                                                                                                                                                                             

前者往往需要對影象邊緣進行編碼,這在很大程度上依賴於影象的分割與邊緣提取,具有相當大的難度和計算量,且一旦待檢測目標局部發生變化,很可能導致操作的失敗。早期主要有Rosenfeld和Freeman等人的方法,後期有CSS等方法。基於影象灰度的方法通過計算點的曲率及梯度來檢測角點,避免了第一類方法存在的缺陷,此類方法主要有Moravec運算元、Forstner運算元、Harris運算元、SUSAN運算元等。

image

這篇文章主要介紹的Harris角點檢測的演算法原理,比較著名的角點檢測方法還有jianbo Shi和Carlo Tomasi提出的Shi-Tomasi演算法,這個演算法開始主要是為了解決跟蹤問題,用來衡量兩幅影象的相似度,我們也可以把它看為Harris演算法的改進。OpenCV中已經對它進行了實現,介面函式名為

GoodFeaturesToTrack()。另外還有一個著名的角點檢測運算元即SUSAN運算元,SUSAN是Smallest Univalue Segment Assimilating Nucleus(最小核值相似區)的縮寫。SUSAN使用一個圓形模板和一個圓的中心點,通過圓中心點畫素與模板圓內其他畫素值的比較,統計出與圓中心畫素近似的像元數量,當這樣的像元數量小於某一個閾值時,就被認為是要檢測的角點。我覺得可以把SUSAN運算元看為Harris演算法的一個簡化。這個演算法原理非常簡單,演算法效率也高,所以在OpenCV中,它的介面函式名稱為:FAST() 。

Part TWO:Harris角點演算法理論

         人眼對角點的識別通常是在一個區域性的小區域或小視窗完成的。如果在各個方向上移動這個特徵的小視窗,視窗內區域的灰度發生了較大的變化,那麼就認為在視窗內遇到了角點。如果這個特定的視窗在影象各個方向上移動時,視窗內影象的灰度沒有發生變化,那麼視窗內就不存在角點;如果視窗在某一個方向移動時,視窗內影象的灰度發生了較大的變化,而在另一些方向上沒有發生變化,那麼,視窗內的影象可能就是一條直線的線段。

image

對於影象I(x,y),當在點(x,y)處平移(Δx,Δy)後的自相似性,可以通過自相關函式給出:

c(x,y;Δx,Δy)=(u,v)W(x,y)w(u,v)(I(u,v)I(u+Δx,v+Δy))2

其中,W(x,y)是以點(x,y)為中心的視窗,w(u,v)為加權函式,它既可是常數,也可以是高斯加權函式。

image

根據泰勒展開,對影象I(x,y)在平移(Δx,Δy)後進行一階近似:

其中,Ix,Iy是影象I(x,y)的偏導數,這樣的話,自相關函式則可以簡化為:

其中

也就是說影象I(x,y)在點(x,y)處平移(Δx,Δy)後的自相關函式可以近似為二項函式:

其中

A=wI2x,B=wI2y,C=wIxIy      二次項函式本質上就是一個橢圓函式。橢圓的扁率和尺寸是M(x,y)的特徵值λ1λ2決定的,橢賀的方向是由M(x,y)的特徵向量決定的, 如下圖所示,橢圓方程為:

 

image

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

  • 影象中的直線。一個特徵值大,另一個特徵值小,λ1λ2λ2λ1。自相關函式值在某一方向上大,在其他方向上小。
  • 影象中的平面。兩個特徵值都小,且近似相等;自相關函式數值在各個方向上都小。
  • 影象中的角點。兩個特徵值都大,且近似相等,自相關函式在所有方向都增大。

    image

根據二次項函式特徵值的計算公式,我們可以求M(x,y)矩陣的特徵值。但是Harris給出的角點差別方法並不需要計算具體的特徵值,而是計算一個角點響應值R來判斷角點。R的計算公式為:

Harris角點演算法實現

 Harris角點的性質

由此,可以得出這樣的結論:增大α的值,將減小角點響應值R,降低角點檢測的靈性,減少被檢測角點的數量;減小α值,將增大角點響應值R,增加角點檢測的靈敏性,增加被檢測角點的數量。

2. Harris角點檢測運算元對亮度和對比度的變化不敏感

這是因為在進行Harris角點檢測時,使用了微分運算元對影象進行微分運算,而微分運算對影象密度的拉昇或收縮和對亮度的擡高或下降不敏感。換言之,對亮度和對比度的仿射變換並不改變Harris響應的極值點出現的位置,但是,由於閾值的選擇,可能會影響角點檢測的數量。

image image

3. Harris角點檢測運算元具有旋轉不變性

Harris角點檢測運算元使用的是角點附近的區域灰度二階矩矩陣。而二階矩矩陣可以表示成一個橢圓,橢圓的長短軸正是二階矩矩陣特徵值平方根的倒數。當特徵橢圓轉動時,特徵值並不發生變化,所以判斷角點響應值R也不發生變化,由此說明Harris角點檢測運算元具有旋轉不變性。

4. Harris角點檢測運算元不具有尺度不變性

如下圖所示,當右圖被縮小時,在檢測視窗尺寸不變的前提下,在視窗內所包含影象的內容是完全不同的。左側的影象可能被檢測為邊緣或曲線,而右側的影象則可能被檢測為一個角點。

image

Harris的OpenCV介面

OpenCV的Hairrs角點檢測的函式為cornerHairrs(),但是它的輸出是一幅浮點值影象,浮點值越高,表明越可能是特徵角點,我們需要對影象進行閾值化。

C++: void cornerHarris(InputArray src, OutputArray dst, int blockSize, int apertureSize, double k, int borderType = BORDER_DEFAULT);
  • src – 輸入的單通道8-bit或浮點影象。
  • dst – 儲存著Harris角點響應的影象矩陣,大小與輸入影象大小相同,是一個浮點型矩陣。
  • blockSize – 鄰域大小。
  • apertureSize – 擴充套件的微分運算元大。
  • k – 響應公式中的,引數α
  • boderType – 邊界處理的型別。
int main()
{
    Mat image = imread("../buliding.png");
    Mat gray;
    cvtColor(image, gray, CV_BGR2GRAY);

    Mat cornerStrength;
    cornerHarris(gray, cornerStrength, 3, 3, 0.01);
    threshold(cornerStrength, cornerStrength, 0.001, 255, THRESH_BINARY);
    return 0;
}

  image     image   image

從上面上間一幅影象我們可以看到,有很多角點都是粘連在一起的,我們下面通過加入非極大值抑制來進一步去除一些粘在一起的角點。

非極大值抑制原理是,在一個視窗內,如果有多個角點則用值最大的那個角點,其他的角點都刪除,視窗大小這裡我們用3*3,程式中通過影象的膨脹運算來達到檢測極大值的目的,因為預設引數的膨脹運算就是用視窗內的最大值替代當前的灰度值。

int main()
{
    Mat image = imread("buliding.png");
    Mat gray;
    cvtColor(image, gray, CV_BGR2GRAY);

    Mat cornerStrength;
    cornerHarris(gray, cornerStrength, 3, 3, 0.01);

    double maxStrength;
    double minStrength;
    // 找到影象中的最大、最小值
    minMaxLoc(cornerStrength, &minStrength, &maxStrength);

    Mat dilated;
    Mat locaMax;
    // 膨脹影象,最找出影象中全部的區域性最大值點
    dilate(cornerStrength, dilated, Mat());
    // compare是一個邏輯比較函式,返回兩幅影象中對應點相同的二值影象
    compare(cornerStrength, dilated, locaMax, CMP_EQ);

    Mat cornerMap;
    double qualityLevel = 0.01;
    double th = qualityLevel*maxStrength; // 閾值計算
    threshold(cornerStrength, cornerMap, th, 255, THRESH_BINARY);
    cornerMap.convertTo(cornerMap, CV_8U);
    // 逐點的位運算
    bitwise_and(cornerMap, locaMax, cornerMap);

    drawCornerOnImage(image, cornerMap);
    namedWindow("result");
    imshow("result", image);
    waitKey();

    return 0;
}
void drawCornerOnImage(Mat& image, const Mat&binary)
{
    Mat_<uchar>::const_iterator it = binary.begin<uchar>();
    Mat_<uchar>::const_iterator itd = binary.end<uchar>();
    for (int i = 0; it != itd; it++, i++)
    {
        if (*it)
            circle(image, Point(i%image.cols, i / image.cols), 3, Scalar(0, 255, 0), 1);
    }
}

現在我們得到的效果就比預設的函式得到的結果有相當的改善,如上面最右邊效果圖。

多尺度Harris角點

1 多尺度Harris角點的原理

雖然Harris角點檢測運算元具有部分影象灰度變化的不變性和旋轉不變性,但它不具有尺度不變性。但是尺度不變性對影象特徵來說至關重要。人們在使用肉眼識別物體時,不管物體遠近,尺寸的變化都能認識物體,這是因為人的眼睛在辨識物體時具有較強的尺度不變性。在影象特徵提取:尺度空間理論這篇文章裡就已經講到了高斯尺度空間的概念。下面將Harris角點檢測運算元與高斯尺度空間表示相結合,使用Harris角點檢測運算元具有尺度的不變性。

2 多尺度Harris角點實現

更多的討論

在上面描述的Harris角點具有光照不變性、旋轉不變性、尺度不變性,但是嚴格意義上來說並不具備仿射不變性。Harris-Affine是一種新穎的檢測仿射不變特徵點的方法,可以處理明顯的仿射變換,包括大尺度變化和明顯的視角變化。Harris-Affine主要是依據了以下三個思路:

  1. 特徵點周圍的二階矩的計算對區域進行的歸一化,具有仿射不變性;
  2. 通過在尺度空間上歸一化微分的區域性極大值求解來精化對應尺度;
  3. 自適應仿射Harris檢測器能夠精確定位牲點;

該文章參考的一下文章:

[1] 《影象區域性不變特徵與描述》王永明,王貴錦。