一、概述
使用 Scharr 算子计算第一个 x 或 y 图像导数。该函数使用 Scharr 算子计算第一个 x 或 y 空间图像导数。 该调用
Scharr(src, dst, ddepth, dx, dy, scale, delta, borderType)
相当于
Sobel(src, dst, ddepth, dx, dy, FILTER_SCHARR, scale, delta, borderType).
当kernel的尺寸为3×3时,Sobel计算的结果不是很精确,为了得到更精确的计算结果常采用下图所示的Scharr kernel:
Scharr变换可以看做是使用了Scharr核的Sobel变换,是一种经过改进的Sobel变换,同样也要区分x和y方向分开计算梯度。
需要注意的是在计算Scharr梯度时,dx和dy要满足如下的关系(实际就是说要么dx=1 并且 dy=0;要么dx=0 并且 dy=1),否则会抛异常:
CV_Assert( dx >= 0 && dy >= 0 && dx+dy == 1 )
也就是每次只能求x方向或者y方向单个方向的梯度,而且只能求一阶梯度,不像Sobel()中dx或dy可以设置为更大的值计算更高阶的梯度。
二、Scharr函数
1、函数原型
cv::Scharr (InputArray src, OutputArray dst, int ddepth, int dx, int dy, double scale=1, double delta=0, int borderType=BORDER_DEFAULT)
2、参数详解
src | 输入图像。 |
dst | 输出与 src 大小和通道数相同的图像。 |
ddepth | 输出图像深度,见组合 |
dx | 导数 x 的阶数。 |
dy | 导数 y 的阶数。 |
scale | 计算导数值的可选比例因子; 默认情况下,不应用缩放(有关详细信息,请参阅 getDerivKernels)。 |
delta | 在将结果存储到 dst 之前添加到结果中的可选增量值。 |
borderType | 像素外推法,请参阅 BorderTypes。 不支持 BORDER_WRAP。 |
三、OpenCV源码
1、源码路径
opencv\modules\imgproc\src\deriv.cpp
2、源码代码
void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy,
double scale, double delta, int borderType )
{
CV_INSTRUMENT_REGION();
CV_Assert(!_src.empty());
int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype);
if (ddepth < 0)
ddepth = sdepth;
int dtype = CV_MAKETYPE(ddepth, cn);
_dst.create( _src.size(), dtype );
int ktype = std::max(CV_32F, std::max(ddepth, sdepth));
Mat kx, ky;
getScharrKernels( kx, ky, dx, dy, false, ktype );
if( scale != 1 )
{
// usually the smoothing part is the slowest to compute,
// so try to scale it instead of the faster differentiating part
if( dx == 0 )
kx *= scale;
else
ky *= scale;
}
CV_OCL_RUN(ocl::isOpenCLActivated() && _dst.isUMat() && _src.dims() <= 2 &&
(size_t)_src.rows() > ky.total() && (size_t)_src.cols() > kx.total(),
ocl_sepFilter3x3_8UC1(_src, _dst, ddepth, kx, ky, delta, borderType));
CV_OCL_RUN(ocl::isOpenCLActivated() && _dst.isUMat() && _src.dims() <= 2 &&
(size_t)_src.rows() > kx.total() && (size_t)_src.cols() > kx.total(),
ocl_sepFilter2D(_src, _dst, ddepth, kx, ky, Point(-1, -1), delta, borderType))
Mat src = _src.getMat();
Mat dst = _dst.getMat();
Point ofs;
Size wsz(src.cols, src.rows);
if(!(borderType & BORDER_ISOLATED))
src.locateROI( wsz, ofs );
CALL_HAL(scharr, cv_hal_scharr, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, ddepth, cn,
ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, dx, dy, scale, delta, borderType&~BORDER_ISOLATED);
//CV_IPP_RUN_FAST(ipp_Deriv(src, dst, dx, dy, 0, scale, delta, borderType));
sepFilter2D( src, dst, ddepth, kx, ky, Point(-1, -1), delta, borderType );
}
四、效果图像示例
