Scharr函式和Sobel函式的混合使用
程式碼如下:
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <stdlib.h> #include <stdio.h> using namespace cv; /** @function main */ int main( int argc, char** argv ) { Mat src, src_gray; Mat grad; char* window_name = "Sobel例子"; int scale = 1; int delta = 0; int ddepth = CV_16S; int c; /// 裝載影象 src = imread( "C://1.jpg" ); if( !src.data ) { return -1; } imshow("原始影象",src); GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT ); //Blur降噪 /// 轉換為灰度圖 cvtColor( src, src_gray, CV_RGB2GRAY ); /// 建立顯示視窗 namedWindow( window_name, CV_WINDOW_AUTOSIZE ); /// 建立 grad_x 和 grad_y 矩陣 Mat grad_x, grad_y; Mat abs_grad_x, abs_grad_y; //Scharr函式與Sobel函式一樣快,但結果更加的精確 /// 求 X方向梯度 Scharr( src_gray, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT ); ksize預設為3 相等於 1,0,3 scale和delta預設 1,0, Scharr( src_gray, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT ); // Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT ); convertScaleAbs( grad_x, abs_grad_x ); imshow("x方向Sobel",abs_grad_x ); /// 求Y方向梯度 Scharr( src_gray, grad_y, ddepth, 0, 1, scale, delta, BORDER_DEFAULT ); // Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, 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, grad ); imshow("整體方向Sobel", grad); waitKey(0); return 0; }
1.首先申明變數:
Mat src, src_gray; Mat grad; char* window_name = “Sobel Demo - Simple Edge Detector”; int scale = 1; int delta = 0; int ddepth = CV_16S;
2.裝載原影象 src:
src = imread( argv[1] ); if( !src.data ) { turn -1; }
3.第一步對原影象使用 GaussianBlur 降噪 ( 核心大小 = 3 )
GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
4.將降噪後的影象轉換為灰度圖:
cvtColor( src, src_gray, CV_RGB2GRAY );
5.第二步,在 x 和 y 方向分別”求導“。 為此,我們使用函式 Sobel :
Mat grad_x, grad_y; Mat abs_grad_x, abs_grad_y;
/// 求 X方向梯度 Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT ); /// 求 Y方向梯度 Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT ); 該函式接受了以下引數:
src_gray: 在本例中為輸入影象,元素型別 CV_8U grad_x/grad_y: 輸出影象. ddepth: 輸出影象的深度,設定為 CV_16S 避免外溢。 x_order: x 方向求導的階數。 y_order: y 方向求導的階數。 scale, delta 和 BORDER_DEFAULT: 使用預設值 注意為了在 x 方向求導我們使用: x_{order}= 1 , y_{order} = 0. 採用同樣方法在 y 方向求導。
6.將中間結果轉換到 CV_8U:
convertScaleAbs( grad_x, abs_grad_x ); convertScaleAbs( grad_y, abs_grad_y );
7.將兩個方向的梯度相加來求取近似 梯度 (注意這裡沒有準確的計算,但是對我們來講已經足夠了)。
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
最後,顯示結果:
imshow( window_name, grad );
測試結果如下 1.Sobel運算元的使用 x y 整體方向上的sobel 2.使用Scharr函式 x,y,整體方向上類似Sobel