opencv图像处理梯度边缘和角点
轉自:http://blog.sina.com.cn/s/blog_4b9b714a0100c9f7.html
?
梯度、邊緣和角點
Sobel
使用擴展 Sobel 算子計算一階、二階、三階或混合圖像差分
?
void cvSobel( const CvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size=3 );
- src
- 輸入圖像. dst
- 輸出圖像. xorder
- x 方向上的差分階數 yorder
- y 方向上的差分階數 aperture_size
- 擴展 Sobel 核的大小,必須是 1, 3, 5 或 7。 除了尺寸為 1, 其它情況下, aperture_size ×aperture_size 可分離內核將用來計算差分。對 aperture_size=1的情況, 使用 3x1 或 1x3 內核(不進行高斯平滑操作)。這里有一個特殊變量 CV_SCHARR (=-1),對應 3x3 Scharr 濾波器,可以給出比 3x3 Sobel 濾波更精確的結果。Scharr 濾波器系數是:
- 對 x-方向 以及轉置矩陣對 y-方向。
函數 cvSobel 通過對圖像用相應的內核進行卷積操作來計算圖像差分:
由于Sobel 算子結合了 Gaussian 平滑和微分,所以,其結果或多或少對噪聲有一定的魯棒性。通常情況,函數調用采用如下參數 (xorder=1, yorder=0, aperture_size=3) 或 (xorder=0, yorder=1, aperture_size=3) 來計算一階 x- 或 y- 方向的圖像差分。第一種情況對應:
核。
第二種對應:
或者
核的選則依賴于圖像原點的定義 (origin 來自 IplImage 結構的定義)。由于該函數不進行圖像尺度變換,所以和輸入圖像(數組)相比,輸出圖像(數組)的元素通常具有更大的絕對數值(譯者注:即象素的深度)。為防止溢出,當輸入圖像是 8 位的,要求輸出圖像是 16 位的。當然可以用函數 cvConvertScale 或 cvConvertScaleAbs 轉換為 8 位的。除了 8-比特 圖像,函數也接受 32-位浮點數圖像。所有輸入和輸出圖像都必須是單通道的,并且具有相同的圖像尺寸或者ROI尺寸。
?
Laplace
計算圖像的 Laplacian 變換
void cvLaplace( const CvArr* src, CvArr* dst, int aperture_size=3 );
- src
- 輸入圖像. dst
- 輸出圖像. aperture_size
- 核大小 (與 cvSobel 中定義一樣).
函數 cvLaplace 計算輸入圖像的 Laplacian變換,方法是先用 sobel 算子計算二階 x- 和 y- 差分,再求和:
dst(x,y) = d2src/dx2 + d2src/dy2
對 aperture_size=1 則給出最快計算結果,相當于對圖像采用如下內核做卷積:
類似于 cvSobel 函數,該函數也不作圖像的尺度變換,所支持的輸入、輸出圖像類型的組合和cvSobel一致。
?
Canny
采用Canny算法做邊緣檢測
?
void cvCanny( const CvArr* image, CvArr* edges, double threshold1, double threshold2, int aperture_size=3 );
- image
- 輸入圖像. edges
- 輸出的邊緣圖像 threshold1
- 第一個閾值 threshold2
- 第二個閾值 aperture_size
- Sobel 算子內核大小 (見 cvSobel).
函數 cvCanny 采用 CANNY 算法發現輸入圖像的邊緣而且在輸出圖像中標識這些邊緣。threshold1和threshold2 當中的
小閾值用來控制邊緣連接,大的閾值用來控制強邊緣的初始分割。
- 注意事項:cvCanny只接受單通道圖像作為輸入。
- 外部鏈接:經典的canny自調整閾值算法的一個opencv的實現見:http://blog.chinaunix.net/u/30231/showart_233944.htm
?
PreCornerDetect
計算用于角點檢測的特征圖,
void cvPreCornerDetect( const CvArr* image, CvArr* corners, int aperture_size=3 );
- image
- 輸入圖像. corners
- 保存候選角點的特征圖 aperture_size
- Sobel 算子的核大小(見cvSobel).
函數 cvPreCornerDetect 計算函數 其中 表示一階圖像差分, 表示二階圖像差分。 角點被認為是函數的局部最大值:
// 假設圖像格式為浮點數 IplImage* corners = cvCloneImage(image); IplImage* dilated_corners = cvCloneImage(image);
IplImage* corner_mask = cvCreateImage( cvGetSize(image), 8, 1 ); cvPreCornerDetect( image, corners, 3 );
cvDilate( corners, dilated_corners, 0, 1 ); cvSubS( corners, dilated_corners, corners );
cvCmpS( corners, 0, corner_mask, CV_CMP_GE );
cvReleaseImage( &corners ); cvReleaseImage( &dilated_corners );
CornerEigenValsAndVecs
計算圖像塊的特征值和特征向量,用于角點檢測
void cvCornerEigenValsAndVecs( const CvArr* image, CvArr* eigenvv, int block_size, int aperture_size=3 );
- image
- 輸入圖像. eigenvv
- 保存結果的數組。必須比輸入圖像寬 6 倍。 block_size
- 鄰域大小 (見討論). aperture_size
- Sobel 算子的核尺寸(見 cvSobel).
對每個象素,函數 cvCornerEigenValsAndVecs 考慮 block_size × block_size 大小的鄰域 S(p),
然后在鄰域上計算圖像差分的相關矩陣:
然后它計算矩陣的特征值和特征向量,并且按如下方式(λ1, λ2, x1, y1, x2, y2)存儲這些值到輸出圖像中,其中
- λ1, λ2 - M 的特征值,沒有排序
- (x1, y1) - 特征向量,對 λ1
- (x2, y2) - 特征向量,對 λ2
CornerMinEigenVal
計算梯度矩陣的最小特征值,用于角點檢測
void cvCornerMinEigenVal( const CvArr* image, CvArr* eigenval, int block_size, int aperture_size=3 );
- image
- 輸入圖像. eigenval
- 保存最小特征值的圖像. 與輸入圖像大小一致 block_size
- 鄰域大小 (見討論 cvCornerEigenValsAndVecs). aperture_size
- Sobel 算子的核尺寸(見 cvSobel). 當輸入圖像是浮點數格式時,該參數表示用來計算差分固定的浮點濾波器的個數.
函數 cvCornerMinEigenVal 與 cvCornerEigenValsAndVecs 類似,但是它僅僅計算和存儲每個象素點差分相關矩陣的最小特征值,
即前一個函數的 min(λ1, λ2)
CornerHarris
哈里斯(Harris)角點檢測
void cvCornerHarris( const CvArr* image, CvArr* harris_responce, int block_size, int aperture_size=3, double k=0.04 );
- image
- 輸入圖像。 harris_responce
- 存儲哈里斯(Harris)檢測responces的圖像。與輸入圖像等大。 block_size
- 鄰域大小(見關于cvCornerEigenValsAndVecs的討論)。 aperture_size
- 擴展 Sobel 核的大小(見 cvSobel)。格式. 當輸入圖像是浮點數格式時,該參數表示用來計算差分固定的浮點濾波器的個數。 k
- Harris detector free parameter. See the formula below.
- harris 檢測器的自由參數。請看如下公式。
- The function cvCornerHarris runs the Harris edge detector on image. Similarly to cvCornerMinEigenVal and
- cvCornerEigenValsAndVecs, for each pixel it calculates 2x2 gradient covariation matrix M
- over block_size×block_size neighborhood. Then, it stores
det(M) - k*trace(M)2 to the destination image. Corners in the image can be found as local maxima of the
destination image.
- 函數 cvCornerHarris 對輸入圖像進行 Harris 邊界檢測。類似于 cvCornerMinEigenVal 和 cvCornerEigenValsAndVecs。
- 對每個像素,在 block_size*block_size 大小的鄰域上,計算其2*2梯度共變矩陣(或相關異變矩陣)M。
- 然后,將 det(M) - k*trace(M)2 (此公式有待考證,最后的“2”是否應為平方符號?這里2應該是平方)保存到輸出圖像中。
- 輸入圖像中的角點在輸出圖像中由局部最大值表示。
FindCornerSubPix
精確角點位置
void cvFindCornerSubPix( const CvArr* image, CvPoint2D32f* corners, int count, CvSize win,CvSize zero_zone, CvTermCriteria criteria );
- image
- 輸入圖像. corners
- 輸入角點的初始坐標,也存儲精確的輸出坐標 count
- 角點數目 win
- 搜索窗口的一半尺寸。如果 win=(5,5) 那么使用 5*2+1 × 5*2+1 = 11 × 11 大小的搜索窗口 zero_zone
- 死區的一半尺寸,死區為不對搜索區的中央位置做求和運算的區域。它是用來避免自相關矩陣出現的某些可能的奇異性。
- 當值為 (-1,-1) 表示沒有死區。 criteria
- 求角點的迭代過程的終止條件。即角點位置的確定,要么迭代數大于某個設定值,或者是精確度達到某個設定值。
- criteria 可以是最大迭代數目,或者是設定的精確度,也可以是它們的組合。
函數 cvFindCornerSubPix 通過迭代來發現具有子象素精度的角點位置,或如圖所示的放射鞍點(radial saddle points)。
子象素級角點定位的實現是基于對向量正交性的觀測而實現的,即從中央點q到其鄰域點p 的向量和p點處的
圖像梯度正交(服從圖像和測量噪聲)。考慮以下的表達式:
εi=DIpiT?(q-pi)
其中,DIpi表示在q的一個鄰域點pi處的圖像梯度,q的值通過最小化εi得到。通過將εi設為0,可以建立系統方程如下:
sumi(DIpi?DIpiT)?q - sumi(DIpi?DIpiT?pi) = 0
其中q的鄰域(搜索窗)中的梯度被累加。調用第一個梯度參數G和第二個梯度參數b,得到:
q=G-1?b
該算法將搜索窗的中心設為新的中心q,然后迭代,直到找到低于某個閾值點的中心位置。
?
GoodFeaturesToTrack
確定圖像的強角點
void cvGoodFeaturesToTrack( const CvArr* image, CvArr* eig_image, CvArr* temp_image,
CvPoint2D32f* corners, int* corner_count, double quality_level, double min_distance, const CvArr* mask=NULL );
- image
- 輸入圖像,8-位或浮點32-比特,單通道 eig_image
- 臨時浮點32-位圖像,尺寸與輸入圖像一致 temp_image
- 另外一個臨時圖像,格式與尺寸與 eig_image 一致 corners
- 輸出參數,檢測到的角點 corner_count
- 輸出參數,檢測到的角點數目 quality_level
- 最大最小特征值的乘法因子。定義可接受圖像角點的最小質量因子。 min_distance
- 限制因子。得到的角點的最小距離。使用 Euclidian 距離 mask
- ROI:感興趣區域。函數在ROI中計算角點,如果 mask 為 NULL,則選擇整個圖像。必須為單通道的灰度圖,大小與輸入圖像相同。
- mask對應的點不為0,表示計算該點。
函數 cvGoodFeaturesToTrack 在圖像中尋找具有大特征值的角點。該函數,首先用cvCornerMinEigenVal
計算輸入圖像的每一個象素點的最小特征值,
并將結果存儲到變量 eig_image 中。然后進行非最大值抑制(僅保留3x3鄰域中的局部最大值)。
下一步將最小特征值小于 quality_level?max(eig_image(x,y)) 排除掉。最后,函數確保所有發現的角點之間具有足夠的距離,
(最強的角點第一個保留,然后檢查新的角點與已有角點之間的距離大于 min_distance )。
總結
以上是生活随笔為你收集整理的opencv图像处理梯度边缘和角点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cvGetSubRect与cvMul用法
- 下一篇: OpenCV 图像采样 插值 几何变换