OpenCV 笔记 -- 边缘检测(Sobel、Laplace、Canny)
OpenCV 筆記 – 邊緣檢測(Sobel、Laplace、Canny)
參考文檔
一、Sobel 算子
1、簡介
Sobel 算子是一個離散的一階差分算子,用來計算圖像亮度函數的一階梯度近似值。在圖像的任何一點使用此算子,將會產生該點對應的梯度矢量或是其法矢量。算子其實是一個模板,用模板與圖像做卷積(協相關)運算。
Sobel 模板(x 和y 方向):
求出近似梯度:
梯度方向:
2、特點
- 具有一定的噪聲魯棒性
- 有邊緣方向信息
3、OpenCV 中的 Sobel 函數
函數原型:
void Sobel (InputArray src, OutputArray dst,int ddepth, int dx, int dy, int ksize=3, double scale=1, double delta=0, int borderType=BORDER_DEFAULT);參數詳解:
-
第一個參數:InputArray 類型的src,為輸入圖像,填Mat類型即可。
-
第二個參數:OutputArray類型的dst,即目標圖像,函數的輸出參數,需要和源圖片有一樣的尺寸和類型。
-
第三個參數:int類型的ddepth,輸出圖像的深度,支持如下src.depth()和ddepth的組合
-
若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F
-
若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F
-
若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F
-
若src.depth() = CV_64F, 取ddepth = -1/CV_64F
-
第四個參數:int類型dx,x 方向上的差分階數。
-
第五個參數:int類型dy,y方向上的差分階數。
-
第六個參數:int類型ksize,有默認值3,表示Sobel核的大小。必須取1,3,5或7。
-
第七個參數:double類型的scale,計算導數值時可選的縮放因子,默認值是1,表示默認情況下是沒有應用縮放的。我們可以在文檔中查閱getDerivKernels的相關介紹,來得到這個參數的更多信息。
-
第八個參數:double類型的delta,表示在結果存入目標圖(第二個參數dst)之前可選的delta值,有默認值0。
-
第九個參數: int類型的borderType,邊界模式,默認值為BORDER_DEFAULT。這個參數可以在官方文檔中borderInterpolate處得到更詳細的信息。
函數使用:
#include <opencv2/opencv.hpp> using namespace cv;int main() {Mat grad_x, grad_y;Mat abs_grad_x, abs_grad_y,dst;// 載入原始圖 Mat src = imread("1.jpg"); // 顯示原始圖 imshow("【原始圖】sobel邊緣檢測", src); // 求 X方向梯度Sobel(src, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT );convertScaleAbs(grad_x, abs_grad_x );imshow("【效果圖】X方向Sobel", abs_grad_x); // 求Y方向梯度Sobel(src, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT );convertScaleAbs( grad_y, abs_grad_y );imshow("【效果圖】Y方向Sobel", abs_grad_y); // 合并梯度(近似)addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst );imshow("【效果圖】Sobel算子", dst); waitKey(0); return 0; }二、Laplace 算子
1、簡介
拉普拉斯算子一個二階微分算子。
Laplace 模板:
2、特點
- 旋轉不變性
- 沒有了邊緣的方向信息
- 雙倍加強了噪聲的影響
3、OpenCV 中的 Sobel 函數
函數原型:
void Laplacian(InputArray src,OutputArray dst, int ddepth, int ksize=1, double scale=1, double delta=0, intborderType=BORDER_DEFAULT);三、Canny 邊緣提取
1、特點
檢測標準:不丟失重要的邊緣,沒有虛假的邊緣
定位標準:實際邊緣與檢測到的邊緣位置之間的偏差最小
單響應標準:將多個響應降低為單個邊緣響應
2、步驟
1) 使用高斯濾波器,以平滑圖像,濾除噪聲。
2) 計算圖像中每個像素點的梯度強度和方向。
可以使用多種邊緣檢測的算子(如Roberts,Prewitt,Sobel等)返回水平 Gx 和垂直 Gy 方向的一階導數值,由此便可以確定像素點的梯度G和方向theta 。
3) 應用非極大值(Non-Maximum Suppression)抑制,以消除邊緣檢測帶來的雜散響應。
對圖像進行梯度計算后,僅僅基于梯度值提取的邊緣仍然很模糊。非極大值抑制則可以幫助將局部最大值之外的所有梯度值抑制為0,對梯度圖像中每個像素進行非極大值抑制的算法是:
- 將當前像素的梯度強度與沿正負梯度方向上的兩個像素進行比較。
- 如果當前像素的梯度強度與另外兩個像素相比最大,則該像素點保留為邊緣點,否則該像素點將被抑制。
通常為了更加精確的計算,在跨越梯度方向的兩個相鄰像素之間使用線性插值來得到要比較的像素梯度。
4) 應用雙閾值(Double-Threshold)檢測來確定真實的和潛在的邊緣。
為了解決由于噪聲和顏色變化引起的一些邊緣像素的雜散響應,必須用弱梯度值過濾邊緣像素,并保留具有高梯度值的邊緣像素,可以通過選擇高低閾值來實現。如果邊緣像素的梯度值高于高閾值,則將其標記為強邊緣像素;如果邊緣像素的梯度值小于高閾值并且大于低閾值,則將其標記為弱邊緣像素;如果邊緣像素的梯度值小于低閾值,則會被抑制。閾值的選擇取決于給定輸入圖像的內容。
5) 通過抑制孤立的弱邊緣最終完成邊緣檢測。
對于弱邊緣像素,因為這些像素可能是從真實邊緣提取也可能是因噪聲或顏色變化引起的。為了獲得準確的結果,應該抑制由后者引起的弱邊緣。通常,由真實邊緣引起的弱邊緣像素將連接到強邊緣像素,而噪聲響應未連接。為了跟蹤邊緣連接,通過查看弱邊緣像素及其8個鄰域像素,只要其中一個為強邊緣像素,則該弱邊緣點就可以保留為真實的邊緣。
3、OpenCV 中 Canny 函數
函數原型:
void Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize=3, bool L2gradient=false)參數詳解:
- 第一個參數:InputArray 類型的 image,輸入圖像,即源圖像,填Mat類的對象即可,且需為單通道8位圖像
- 第二個參數:OutputArray 類型的 edges,輸出的邊緣圖,需要和源圖片有一樣的尺寸和類型
- 第三個參數:double 類型的 threshold1,第一個滯后性閾值
- 第四個參數:double 類型的 threshold2,第二個滯后性閾值
- 第五個參數:int 類型的 apertureSize,表示應用 Sobel 算子的模板大小,默認值3
- 第六個參數:bool 類型的 L2gradient,一個計算圖像梯度幅值的標識,默認值false
函數使用:
#include <opencv2/opencv.hpp> using namespace cv;int main() {//載入原始圖 Mat src = imread("1.jpg"); //進行Canny邊緣檢測 Canny(src, src, 150, 100, 3 );//顯示邊緣檢測的結果圖imshow("【效果圖】Canny邊緣檢測", src);waitKey(0); return 0; }總結
以上是生活随笔為你收集整理的OpenCV 笔记 -- 边缘检测(Sobel、Laplace、Canny)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Pandas 操作 csv 文件
- 下一篇: 机器学习性能评估指标汇总