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