1. 程式人生 > >Scharr函式和Sobel函式的混合使用

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 在這裡插入圖片描述