Canny函數利用Canny算法來進行圖像的邊緣檢測。算法
須要注意的是,這個函數閾值1和閾值2二者的小者用於邊緣鏈接,而大者用來控制強邊緣的初始段,推薦的高低閾值比在2:1到3:1之間函數
dem:1:字體
demo2:ui
//-----------------------------------【頭文件包含部分】--------------------------------------- // 描述:包含程序所依賴的頭文件 //---------------------------------------------------------------------------------------------- #include <opencv2/opencv.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> //-----------------------------------【命名空間聲明部分】--------------------------------------- // 描述:包含程序所使用的命名空間 //----------------------------------------------------------------------------------------------- using namespace cv; //-----------------------------------【main( )函數】-------------------------------------------- // 描述:控制檯應用程序的入口函數,咱們的程序從這裏開始 //----------------------------------------------------------------------------------------------- int main( ) { //載入原始圖 Mat src = imread("1.jpg"); //工程目錄下應該有一張名爲1.jpg的素材圖 Mat src1=src.clone(); //顯示原始圖 imshow("【原始圖】Canny邊緣檢測", src); //---------------------------------------------------------------------------------- // 1、最簡單的canny用法,拿到原圖後直接用。 //---------------------------------------------------------------------------------- Canny( src, src, 150, 100,3 ); imshow("【效果圖】Canny邊緣檢測", src); //---------------------------------------------------------------------------------- // 2、高階的canny用法,轉成灰度圖,降噪,用canny,最後將獲得的邊緣做爲掩碼,拷貝原圖到效果圖上,獲得彩色的邊緣圖 //---------------------------------------------------------------------------------- Mat dst,edge,gray; // 【1】建立與src同類型和大小的矩陣(dst) dst.create( src1.size(), src1.type() ); // 【2】將原圖像轉換爲灰度圖像 cvtColor( src1, gray, CV_BGR2GRAY ); // 【3】先用使用 3x3內核來降噪 blur( gray, edge, Size(3,3) ); // 【4】運行Canny算子 Canny( edge, edge, 3, 9,3 ); //【5】將g_dstImage內的全部元素設置爲0 dst = Scalar::all(0); //【6】使用Canny算子輸出的邊緣圖g_cannyDetectedEdges做爲掩碼,來將原圖g_srcImage拷到目標圖g_dstImage中 src1.copyTo( dst, edge); //【7】顯示效果圖 imshow("【效果圖】Canny邊緣檢測2", dst); waitKey(0); return 0; }
Sobel函數使用擴展的 Sobel 算子,來計算一階、二階、三階或混合圖像差分spa
C++: 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處獲得更詳細的信息。
通常狀況下,都是用ksize x ksize內核來計算導數的。然而,有一種特殊狀況——當ksize爲1時,每每會使用3 x 1或者1 x 3的內核。且這種狀況下,並無進行高斯平滑操做。.net
demo1:code
調用Sobel函數的實例代碼以下。這裏只是教你們如何使用Sobel函數,就沒有先用一句cvtColor將原圖;轉化爲灰度圖,而是直接用彩色圖操做。對象
//-----------------------------------【頭文件包含部分】--------------------------------------- // 描述:包含程序所依賴的頭文件 //---------------------------------------------------------------------------------------------- #include <opencv2/opencv.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> //-----------------------------------【命名空間聲明部分】--------------------------------------- // 描述:包含程序所使用的命名空間 //----------------------------------------------------------------------------------------------- using namespace cv; //-----------------------------------【main( )函數】-------------------------------------------- // 描述:控制檯應用程序的入口函數,咱們的程序從這裏開始 //----------------------------------------------------------------------------------------------- int main( ) { //【0】建立 grad_x 和 grad_y 矩陣 Mat grad_x, grad_y; Mat abs_grad_x, abs_grad_y,dst; //【1】載入原始圖 Mat src = imread("1.jpg"); //工程目錄下應該有一張名爲1.jpg的素材圖 //【2】顯示原始圖 imshow("【原始圖】sobel邊緣檢測", src); //【3】求 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); //【4】求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); //【5】合併梯度(近似) addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst ); imshow("【效果圖】總體方向Sobel", dst); waitKey(0); return 0; }
C++: void Laplacian(InputArray src,OutputArray dst, int ddepth, int ksize=1, double scale=1, double delta=0, intborderType=BORDER_DEFAULT );
Laplacian( )函數其實主要是利用sobel算子的運算。它經過加上sobel算子運算出的圖像x方向和y方向上的導數,來獲得咱們載入圖像的拉普拉斯變換結果。blog
demo1:教程
//-----------------------------------【頭文件包含部分】--------------------------------------- // 描述:包含程序所依賴的頭文件 //---------------------------------------------------------------------------------------------- #include <opencv2/opencv.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> //-----------------------------------【命名空間聲明部分】--------------------------------------- // 描述:包含程序所使用的命名空間 //----------------------------------------------------------------------------------------------- using namespace cv; //-----------------------------------【main( )函數】-------------------------------------------- // 描述:控制檯應用程序的入口函數,咱們的程序從這裏開始 //----------------------------------------------------------------------------------------------- int main( ) { //【0】變量的定義 Mat src,src_gray,dst, abs_dst; //【1】載入原始圖 src = imread("1.jpg"); //工程目錄下應該有一張名爲1.jpg的素材圖 //【2】顯示原始圖 imshow("【原始圖】圖像Laplace變換", src); //【3】使用高斯濾波消除噪聲 GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT ); //【4】轉換爲灰度圖 cvtColor( src, src_gray, CV_RGB2GRAY ); //【5】使用Laplace函數 Laplacian( src_gray, dst, CV_16S, 3, 1, 0, BORDER_DEFAULT ); //【6】計算絕對值,並將結果轉換成8位 convertScaleAbs( dst, abs_dst ); //【7】顯示效果圖 imshow( "【效果圖】圖像Laplace變換", abs_dst ); waitKey(0); return 0; }
4.綜合代碼彙總
//-----------------------------------【程序說明】---------------------------------------------- // 程序名稱::《【OpenCV入門教程之十二】OpenCV邊緣檢測:Canny算子,Sobel算子,Laplace算子,Scharr濾波器合輯合輯》 博文配套源碼 // 開發所用IDE版本:Visual Studio 2010 // <span style="white-space:pre"> </span>開發所用OpenCV版本: 2.4.9 // 2014年5月11日 Create by 淺墨 // 淺墨的微博:@淺墨_毛星雲 http://weibo.com/1723155442/profile?topnav=1&wvr=5&user=1 // 淺墨的知乎:http://www.zhihu.com/people/mao-xing-yun // 淺墨的豆瓣:http://www.douban.com/people/53426472/ //---------------------------------------------------------------------------------------------- //-----------------------------------【頭文件包含部分】--------------------------------------- // 描述:包含程序所依賴的頭文件 //---------------------------------------------------------------------------------------------- #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> //-----------------------------------【命名空間聲明部分】-------------------------------------- // 描述:包含程序所使用的命名空間 //----------------------------------------------------------------------------------------------- using namespace cv; //-----------------------------------【全局變量聲明部分】-------------------------------------- // 描述:全局變量聲明 //----------------------------------------------------------------------------------------------- //原圖,原圖的灰度版,目標圖 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; //-----------------------------------【全局函數聲明部分】-------------------------------------- // 描述:全局函數聲明 //----------------------------------------------------------------------------------------------- static void ShowHelpText( ); static void on_Canny(int, void*);//Canny邊緣檢測窗口滾動條的回調函數 static void on_Sobel(int, void*);//Sobel邊緣檢測窗口滾動條的回調函數 void Scharr( );//封裝了Scharr邊緣檢測相關代碼的函數 //-----------------------------------【main( )函數】-------------------------------------------- // 描述:控制檯應用程序的入口函數,咱們的程序從這裏開始 //----------------------------------------------------------------------------------------------- int main( int argc, char** argv ) { //改變console字體顏色 system("color 2F"); //顯示歡迎語 ShowHelpText(); //載入原圖 g_srcImage = imread("1.jpg"); if( !g_srcImage.data ) { printf("Oh,no,讀取srcImage錯誤~! \n"); return false; } //顯示原始圖 namedWindow("【原始圖】"); imshow("【原始圖】", g_srcImage); // 建立與src同類型和大小的矩陣(dst) g_dstImage.create( g_srcImage.size(), g_srcImage.type() ); // 將原圖像轉換爲灰度圖像 cvtColor( g_srcImage, g_srcGrayImage, CV_BGR2GRAY ); // 建立顯示窗口 namedWindow( "【效果圖】Canny邊緣檢測", CV_WINDOW_AUTOSIZE ); namedWindow( "【效果圖】Sobel邊緣檢測", CV_WINDOW_AUTOSIZE ); // 建立trackbar createTrackbar( "參數值:", "【效果圖】Canny邊緣檢測", &g_cannyLowThreshold, 120, on_Canny ); createTrackbar( "參數值:", "【效果圖】Sobel邊緣檢測", &g_sobelKernelSize, 3, on_Sobel ); // 調用回調函數 on_Canny(0, 0); on_Sobel(0, 0); //調用封裝了Scharr邊緣檢測代碼的函數 Scharr( ); //輪詢獲取按鍵信息,若按下Q,程序退出 while((char(waitKey(1)) != 'q')) {} return 0; } //-----------------------------------【ShowHelpText( )函數】---------------------------------- // 描述:輸出一些幫助信息 //---------------------------------------------------------------------------------------------- static void ShowHelpText() { //輸出一些幫助信息 printf( "\n\n\t嗯。運行成功,請調整滾動條觀察圖像效果~\n\n" "\t按下「q」鍵時,程序退出~!\n" "\n\n\t\t\t\t by淺墨" ); } //-----------------------------------【on_Canny( )函數】---------------------------------- // 描述:Canny邊緣檢測窗口滾動條的回調函數 //----------------------------------------------------------------------------------------------- void on_Canny(int, void*) { // 先使用 3x3內核來降噪 blur( g_srcGrayImage, g_cannyDetectedEdges, Size(3,3) ); // 運行咱們的Canny算子 Canny( g_cannyDetectedEdges, g_cannyDetectedEdges, g_cannyLowThreshold, g_cannyLowThreshold*3, 3 ); //先將g_dstImage內的全部元素設置爲0 g_dstImage = Scalar::all(0); //使用Canny算子輸出的邊緣圖g_cannyDetectedEdges做爲掩碼,來將原圖g_srcImage拷到目標圖g_dstImage中 g_srcImage.copyTo( g_dstImage, g_cannyDetectedEdges); //顯示效果圖 imshow( "【效果圖】Canny邊緣檢測", g_dstImage ); } //-----------------------------------【on_Sobel( )函數】---------------------------------- // 描述:Sobel邊緣檢測窗口滾動條的回調函數 //----------------------------------------------------------------------------------------- void on_Sobel(int, void*) { // 求 X方向梯度 Sobel( g_srcImage, g_sobelGradient_X, CV_16S, 1, 0, (2*g_sobelKernelSize+1), 1, 1, BORDER_DEFAULT ); convertScaleAbs( g_sobelGradient_X, g_sobelAbsGradient_X );//計算絕對值,並將結果轉換成8位 // 求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 );//計算絕對值,並將結果轉換成8位 // 合併梯度 addWeighted( g_sobelAbsGradient_X, 0.5, g_sobelAbsGradient_Y, 0.5, 0, g_dstImage ); //顯示效果圖 imshow("【效果圖】Sobel邊緣檢測", g_dstImage); } //-----------------------------------【Scharr( )函數】---------------------------------- // 描述:封裝了Scharr邊緣檢測相關代碼的函數 //----------------------------------------------------------------------------------------- void Scharr( ) { // 求 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); }
參考:https://blog.csdn.net/poem_qianmo/article/details/25560901