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); }
自行參透,樓主不懂