日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenCV学习笔记(十二):边缘检测:Canny(),Sobel(),Laplace(),Scharr滤波器

發布時間:2024/7/23 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV学习笔记(十二):边缘检测:Canny(),Sobel(),Laplace(),Scharr滤波器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

OpenCV學習筆記(十二):邊緣檢測:Canny(),Sobel(),Laplace(),Scharr濾波器

1)濾波:邊緣檢測的算法主要是基于圖像強度的一階和二階導數,但導數通常對噪聲很敏感,因此必須采用濾波器來改善與噪聲有關的邊緣檢測器的性能。常見的濾波方法主要有高斯濾波,即采用離散化的高斯函數產生一組歸一化的高斯核,然后基于高斯核函數對圖像灰度矩陣的每一點進行加權求和。
2)增強:增強邊緣的基礎是確定圖像各點鄰域強度的變化值。增強算法可以將圖像灰度點鄰域強度值有顯著變化的點凸顯出來。在具體編程實現時,可通過計算梯度幅值來確定。
3)檢測:經過增強的圖像,往往鄰域中有很多點的梯度值比較大,而在特定的應用中,這些點并不是我們要找的邊緣點,所以應該采用某種方法來對這些點進行取舍。實際工程中,常用的方法是通過閾值化方法來檢測。

1、Canny()算子:

Canny邊緣檢測算子是一個多級邊緣檢測算法

C++: void Canny(InputArray image, //輸入圖像,即源圖像 OutputArray edges, // 輸出的邊緣圖 double threshold1, // 第一個滯后性閾值 double threshold2, // 第二個滯后性閾值// 這個函數閾值1和閾值2兩者的小者用于邊緣連接,而大者用來控制強邊緣的初始段,推薦的高低閾值比在2:1到3:1之間。 int apertureSize=3, // 表示應用Sobel算子的孔徑大小 bool L2gradient=false // 一個計算圖像梯度幅值的標識 )

2、Sobel()算子:

Sobel 算子是一個主要用作邊緣檢測的離散微分算子 (discrete differentiation operator)。它Sobel算子結合了高斯平滑和微分求導,用來計算圖像灰度函數的近似梯度。在圖像的任何一點使用此算子,將會產生對應的梯度矢量或是其法矢量。

void Sobel ( InputArray src, // 輸入圖 OutputArray dst, // 輸出圖 int 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, // 計算導數值時可選的縮放因子 double delta=0, // 表示在結果存入目標圖之前可選的delta值 int borderType=BORDER_DEFAULT // 邊界模式 );

3、Laplace()算子:

Laplacian 算子是n維歐幾里德空間中的一個二階微分算子,定義為梯度grad()的散度div()。Laplacian( )函數其實主要是利用sobel算子的運算。它通過加上sobel算子運算出的圖像x方向和y方向上的導數,來得到我們載入圖像的拉普拉斯變換結果。

void Laplacian(InputArray src, // 源圖像 OutputArray dst, // 輸出的邊緣圖 int ddepth, // 輸出圖像的深度 int ksize=1, // 用于計算二階導數的濾波器的孔徑尺寸 double scale=1, // 計算拉普拉斯值的時候可選的比例因子 double delta=0, // 表示在結果存入目標圖之前可選的delta值 intborderType=BORDER_DEFAULT // 邊界模式 );

4、scharr濾波器:

scharr一般我就直接稱它為濾波器,而不是算子,主要是配合Sobel算子的運算而存在的。
scharr算子與Sobel的不同點是在平滑部分,這里所用的平滑算子是1/16?[3,10,3],相比于1/4?[1,2,1],中心元素占的權重更重,這可能是相對于圖像這種隨機性較強的信號,鄰域相關性不大,所以鄰域平滑應該使用相對較小的標準差的高斯函數,也就是更瘦高的模板。

void Scharr( InputArray src, // 源圖OutputArray dst, // 目標圖int ddepth, // 圖像深度int dx, // x方向上的差分階數int dy, //y方向上的差分階數double scale=1, //縮放因子double delta=0, // delta值intborderType=BORDER_DEFAULT // 邊界模式)

4、代碼示例:

#include <opencv2/opencv.hpp>using namespace cv; using namespace std;//原圖,原圖的灰度版,目標圖 Mat g_srcImage, g_srcGrayImage,g_dstImage;//Canny邊緣檢測相關變量 Mat g_cannyDetectedEdges; int g_cannyLowThreshold=1;//TrackBar位置參數 //Sobel邊緣檢測相關變量 Mat g_sobelGradient_X, g_sobelGradient_Y; Mat g_sobelAbsGradient_X, g_sobelAbsGradient_Y; int g_sobelKernelSize=1;//TrackBar位置參數 //Scharr濾波器相關變量 Mat g_scharrGradient_X, g_scharrGradient_Y; Mat g_scharrAbsGradient_X, g_scharrAbsGradient_Y;int main() {//載入原圖g_srcImage = imread("F:/C++/2. OPENCV 3.1.0/7.1 edge detection 邊緣檢測/5.jpg");if( !g_srcImage.data ) { printf("Oh,no,讀取srcImage錯誤~! \n"); return false; }//顯示原始圖namedWindow("【原始圖】");imshow("【原始圖】", g_srcImage);// 1、創建與src同類型和大小的矩陣(dst)g_dstImage.create( g_srcImage.size(), g_srcImage.type() );// 2、將原圖像轉換為灰度圖像cvtColor( g_srcImage, g_srcGrayImage, COLOR_BGR2GRAY );// 3、創建trackbarnamedWindow( "【效果圖】Canny邊緣檢測", WINDOW_AUTOSIZE );namedWindow( "【效果圖】Sobel邊緣檢測", WINDOW_AUTOSIZE );createTrackbar( "參數值:", "【效果圖】Canny邊緣檢測", &g_cannyLowThreshold, 120, on_Canny);createTrackbar( "參數值:", "【效果圖】Sobel邊緣檢測", &g_sobelKernelSize, 3, on_Sobel);// 4、調用回調函數on_Canny(0, 0);on_Sobel(0, 0);// 5、調用封裝了Scharr邊緣檢測代碼的函數Scharr( );//輪詢獲取按鍵信息,若按下Q,程序退出while((char(waitKey(1)) != 'q')) {} }

1)Canny邊緣檢測窗口滾動條的回調函數

void on_Canny(int, void*) {// 先使用 3x3內核來降噪blur( g_srcGrayImage, g_cannyDetectedEdges, Size(3,3) );// 運行我們的Canny算子// threshold1:滯后性閾值1(較小值用于邊緣連接,較大值控制強邊緣的初始段)// threshold2:滯后性閾值2// apertureSize sobel算子的孔徑大小Canny( g_cannyDetectedEdges, g_cannyDetectedEdges, g_cannyLowThreshold, g_cannyLowThreshold*3, 3 );//先將g_dstImage內的所有元素設置為0g_dstImage = Scalar::all(0);//使用Canny算子輸出的邊緣圖g_cannyDetectedEdges作為掩碼,來將原圖g_srcImage拷到目標圖g_dstImage中g_srcImage.copyTo( g_dstImage, g_cannyDetectedEdges);//顯示效果圖imshow( "【效果圖】Canny邊緣檢測", g_dstImage ); }

2)Sobel邊緣檢測窗口滾動條的回調函數

void on_Sobel(int, void*) {//Sobel算子是一階導數的邊緣檢測算子,在算法實現過程中,通過3×3模板作為核與圖像中的每個像素點做卷積和運算,然后選取合適的閾值以提取邊緣。//Sobel算子算法的優點是計算簡單,速度快。但是由于只采用了2個方向的模板,只能檢測水平和垂直方向的邊緣,//因此這種算法對于紋理較為復雜的圖像,其邊緣檢測效果就不是很理想。該算法認為://凡灰度新值大于或等于閾值的像素點時都是邊緣點。//這種判斷欠合理,會造成邊緣點的誤判,因為許多噪聲點的灰度值也很大。// ddepth:輸出圖像的深度// dx,dy: x y方向上的差分階數// scale :計算導數時的縮放因子// 求 X方向梯度Sobel( g_srcImage, g_sobelGradient_X, CV_16S, 1, 0, (2*g_sobelKernelSize+1), 1, 1, BORDER_DEFAULT );// 對于輸入數組的每個元素,convertScaleAbs函數依次執行三個操作:縮放、取絕對值、轉換為無符號8位類型 :// dst(I)=saturate\_cast<uchar>(|src(I)?alpha+beta|)convertScaleAbs( g_sobelGradient_X, g_sobelAbsGradient_X ); // Mat grad_xROI(grad_x,Rect(0,0,20,20)); // cout<<"M="<<endl<<grad_xROI<<endl; // imshow("【效果圖】 X方向Sobel1", grad_x);// 求Y方向梯度Sobel( g_srcImage, g_sobelGradient_Y, CV_16S, 0, 1, (2*g_sobelKernelSize+1), 1, 1, BORDER_DEFAULT );convertScaleAbs( g_sobelGradient_Y, g_sobelAbsGradient_Y );// 合并梯度addWeighted( g_sobelAbsGradient_X, 0.5, g_sobelAbsGradient_Y, 0.5, 0, g_dstImage );//顯示效果圖imshow("【效果圖】Sobel邊緣檢測", g_dstImage);}

3)Scharr邊緣檢測相關代碼的函數

void Scharr( ) {// scharr算子與Sobel的不同點是在平滑部分,這里所用的平滑算子是1/16?[3,10,3],// 相比于1/4?[1,2,1],中心元素占的權重更重,這可能是相對于圖像這種隨機性較強的信號,// 鄰域相關性不大,所以鄰域平滑應該使用相對較小的標準差的高斯函數,也就是更瘦高的模板。// 求 X方向梯度Scharr( g_srcImage, g_scharrGradient_X, CV_16S, 1, 0, 1, 0, BORDER_DEFAULT );convertScaleAbs( g_scharrGradient_X, g_scharrAbsGradient_X );//計算絕對值,并將結果轉換成8位// 求Y方向梯度Scharr( g_srcImage, g_scharrGradient_Y, CV_16S, 0, 1, 1, 0, BORDER_DEFAULT );convertScaleAbs( g_scharrGradient_Y, g_scharrAbsGradient_Y );//計算絕對值,并將結果轉換成8位// 合并梯度addWeighted( g_scharrAbsGradient_X, 0.5, g_scharrAbsGradient_Y, 0.5, 0, g_dstImage );//顯示效果圖imshow("【效果圖】Scharr濾波器", g_dstImage); }

結果:


總結

以上是生活随笔為你收集整理的OpenCV学习笔记(十二):边缘检测:Canny(),Sobel(),Laplace(),Scharr滤波器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。