- 差分在边缘检測的角色
- Sobel算子
- OpenCV sobel函数
- OpenCV Scharr函数
- prewitt算子
- Roberts算子
- 是离散差分算子.
- 结合了高斯滤波.
是原始图像:
-
我们计算水平和竖直方向的梯度:
-
水平方向: Gx是我们Kernel size为3的水平sober算子,与I作卷积
-
竖直方向:Gy是我们Kernel size为3的水平sober算子,与I作卷积
-
-
对每一个点,再计算以下的值,得到方向无关梯度
有时候也能够这样计算:
-
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
)
-
- src – 输入.
- dst – 输出
- ddepth –
-
output image depth; the following combinations of
src.depth() and
ddepth are supported:
-
- 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
when ddepth=-1, the destination image will have the same depth as the source; in the case of 8-bit input images it will result in truncated derivatives.这里要特别注意了,我们的depth不能为-1,由于我们的输入是uchar8类型的,而算出来的值可能>255也可能 <0 ,都会被截断,CV_16S是推荐的
-
- xorder – order of the derivative x.
- yorder – order of the derivative y.
- ksize – sobel核大小,必须为1, 3, 5, or 7.
- scale – 扩大系数
- delta – 附加系数
- borderType – 边界类型
计算的时候,利用了可分离的滤波进行加速(Ksize=1的时候,用了1*3和 3*1的算子,无法加速)
当Ksize = 3,Sobel採用的算子会不准确,因此还有特殊的值ksize = CV_SCHARR(-1) 相当于使用 Scharr filter 比 Sobel算子能获得更准确的结果. Scharr 算子例如以下
-
C++:
void
Scharr
(InputArray
src, OutputArray
dst, int
ddepth, int
dx, int
dy, double
scale=1, double
delta=0, int
borderType=BORDER_DEFAULT
)
-
- src – input image.
- dst – output image of the same size and the same number of channels as src.
- ddepth – output image depth (see Sobel() for the list of supported combination of src.depth() and ddepth).
- dx – order of the derivative x.
- dy – order of the derivative y.
- scale – optional scale factor for the computed derivative values; by default, no scaling is applied (see getDerivKernels() for details).
- delta – optional delta value that is added to the results prior to storing them in dst.
- borderType – pixel extrapolation method (see borderInterpolate() for details).
The function computes the first x- or y- spatial image derivative using the Scharr operator. The call
is equivalent to
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
using namespace cv;
int main( int, char** argv )
{
Mat src, src_gray;
Mat grad;
const char* window_name = "Sobel Demo - Simple Edge Detector";
//由于以Sobel方式求完导数后会有负值,还有会大于255的值而你建的Sobel的图像是 CV_8U,也就是8位无符号数,所以Sobel建立的图像位数不够,要16位有符号的,也就是 CV_16S
int ddepth = CV_16S;
src = imread( argv[1] );
if( !src.data )
{ return -1; }
GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
cvtColor( src, src_gray, CV_RGB2GRAY );
namedWindow( window_name, CV_WINDOW_AUTOSIZE );
// Generate grad_x and grad_y
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
// Gradient X
//Scharr( src_gray, grad_x, ddepth, 1, 0);
Sobel( src_gray, grad_x, ddepth, 1, 0, 3);
convertScaleAbs( grad_x, abs_grad_x );
// Gradient Y
//Scharr( src_gray, grad_y, ddepth, 0, 1);
Sobel( src_gray, grad_y, ddepth, 0, 1, 3);
convertScaleAbs( grad_y, abs_grad_y );
// Total Gradient (approximate)
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
imshow( window_name, grad );
waitKey(0);
return 0;
}
效果图:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
int main( int, char** argv )
{
Mat src,gray,Kernelx,Kernely;
src = imread( argv[1] );
cvtColor( src, gray, CV_RGB2GRAY );
namedWindow("srcImage", 1);
namedWindow("dstImage", 1);
Kernelx = (Mat_<double>(3,3) << 1, 1, 1, 0, 0, 0, -1, -1, -1);
Kernely = (Mat_<double>(3,3) << -1, 0, 1, -1, 0, 1, -1, 0, 1);
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y, grad;
filter2D(gray, grad_x, CV_16S , Kernelx, Point(-1,-1));
filter2D(gray, grad_y, CV_16S , Kernely, Point(-1,-1));
convertScaleAbs( grad_x, abs_grad_x );
convertScaleAbs( grad_y, abs_grad_y );
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
imshow("dstImage", grad);
waitKey();
return 0;
}
效果图: