代码如下:
#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