一、概述
模糊图像并对其进行下采样。默认情况下,输出图像的大小计算为 Size((src.cols+1)/2, (src.rows+1)/2),但无论如何,应满足以下条件:
该函数执行高斯金字塔构造的下采样步骤。 首先,它将源图像与内核进行卷积:
然后,它通过移除偶数行和列来对图像进行下采样。这里的down是指图像变小,所以原始图像在金字塔的底部。首先将当前层的图像和上面这个高斯核卷积。
这个高斯核的尺寸为5×5大小,所有元素的值加起来正好为256,最后再除以256,得到的加权和正好为1。其距离最中心越近数值越大,这正好和高斯平滑选择的高斯核类似。
这个过程也类似于高斯平滑,可以看到经过pyrDown()处理的图像变得更加模糊(平滑)。然后移除偶数行和偶数列,然后就能得到和原图相比是原图1/4大小的新的图像,在图像金字塔中就位于当前层的上一层。
二、pyrDown函数
1、函数原型
cv::pyrDown (InputArray src, OutputArray dst, const Size &dstsize=Size(), int borderType=BORDER_DEFAULT)
2、参数详解
src | 输入图像。 |
dst | 输出图像; 它具有指定的大小和与 src 相同的类型。 |
dstsize | 输出图像的大小。 |
borderType | 像素外推法,请参阅 BorderTypes(不支持 BORDER_CONSTANT) |
三、OpenCV源码
1、源码路径
opencv\modules\imgproc\src\pyramids.cpp
2、源码代码
void cv::pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType )
{
CV_INSTRUMENT_REGION();
CV_Assert(borderType != BORDER_CONSTANT);
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
ocl_pyrDown(_src, _dst, _dsz, borderType))
CV_OVX_RUN(_src.dims() <= 2,
openvx_pyrDown(_src, _dst, _dsz, borderType))
Mat src = _src.getMat();
Size dsz = _dsz.empty() ? Size((src.cols + 1)/2, (src.rows + 1)/2) : _dsz;
_dst.create( dsz, src.type() );
Mat dst = _dst.getMat();
int depth = src.depth();
CALL_HAL(pyrDown, cv_hal_pyrdown, src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows, depth, src.channels(), borderType);
#ifdef HAVE_IPP
bool isolated = (borderType & BORDER_ISOLATED) != 0;
int borderTypeNI = borderType & ~BORDER_ISOLATED;
#endif
CV_IPP_RUN(borderTypeNI == BORDER_DEFAULT && (!_src.isSubmatrix() || isolated) && dsz == Size((_src.cols() + 1)/2, (_src.rows() + 1)/2),
ipp_pyrdown( _src, _dst, _dsz, borderType));
PyrFunc func = 0;
if( depth == CV_8U )
func = pyrDown_< FixPtCast<uchar, 8> >;
else if( depth == CV_16S )
func = pyrDown_< FixPtCast<short, 8> >;
else if( depth == CV_16U )
func = pyrDown_< FixPtCast<ushort, 8> >;
else if( depth == CV_32F )
func = pyrDown_< FltCast<float, 8> >;
else if( depth == CV_64F )
func = pyrDown_< FltCast<double, 8> >;
else
CV_Error( CV_StsUnsupportedFormat, "" );
func( src, dst, borderType );
}
四、效果图像示例
下面的例子采用python代码,进行了连续3次进行pyrDown,得到三张新的图片,对应了金字塔中的三个级别,们可以使用cv2.pyrDown()和cv2.pyrUp()函数得到高斯金字塔。
img = cv2.imread('..\\messi5.jpg')
img_down = cv2.pyrDown(img,dstsize=(img.shape[1]//2,img.shape[0]//2))
img_down2 = cv2.pyrDown(img_down,dstsize=(img_down.shape[1]//2,img_down.shape[0]//2))
img_down3 = cv2.pyrDown(img_down2,dstsize=(img_down2.shape[1]//2,img_down2.shape[0]//2))