源码溯源:(resize函数位于..\opencv\sources\modules\imgproc\src\resize.cpp中),如下
void cv::resize( InputArray _src,
OutputArray _dst,
Size dsize,
double inv_scale_x,
double inv_scale_y,
int interpolation )
{
CV_INSTRUMENT_REGION()
Size ssize = _src.size();
CV_Assert( ssize.width > 0 && ssize.height > 0 );
CV_Assert( dsize.area() > 0 || (inv_scale_x > 0 && inv_scale_y > 0) );
if( dsize.area() == 0 )
{
dsize = Size(saturate_cast(ssize.width*inv_scale_x),
saturate_cast(ssize.height*inv_scale_y));
CV_Assert( dsize.area() > 0 );
}
else
{
inv_scale_x = (double)dsize.width/ssize.width;
inv_scale_y = (double)dsize.height/ssize.height;
}
if (interpolation == INTER_LINEAR_EXACT && (_src.depth() == CV_32F || _src.depth() == CV_64F))
interpolation = INTER_LINEAR; // If depth isn't supported fallback to generic resize
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat() && _src.cols() > 10 && _src.rows() > 10,
ocl_resize(_src, _dst, dsize, inv_scale_x, inv_scale_y, interpolation))
Mat src = _src.getMat();
_dst.create(dsize, src.type());
Mat dst = _dst.getMat();
if (dsize == ssize)
{
// Source and destination are of same size. Use simple copy.
src.copyTo(dst);
return;
}
hal::resize(src.type(), src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows, inv_scale_x, inv_scale_y, interpolation);
}
简版:
void cv::resize( InputArray _src,
OutputArray _dst,
Size dsize,
double inv_scale_x = 0,
double inv_scale_y = 0,
int interpolation = INTER_LINEAR )
参数解析:
要缩小图像,一般情况下用INTER_AREA来插值;而若要放大图像,一般情况下用INTER_CUBIC(效率不高,不推荐)或INTER_LINEAR(效率高,推荐)
<1>resize函数代码示例:
#include
using namespace cv;
int main() {
//载入原图
Mat srcImage = imread("1.jpg");
Mat temImage, dstImage1, dstImage2;//临时变量和目标图的定义
temImage = srcImage;
//显示原图
imshow("【原始图】", srcImage);
//进行尺寸调整操作
resize(temImage, dstImage1, Size(temImage.cols / 2, temImage.rows / 2), (0, 0), (0, 0), 3);
resize(dstImage1, dstImage2, Size(dstImage1.cols / 2, dstImage1.rows / 2), (0, 0)(0, 0), 3);
//显示效果图
imshow("【效果图一】", dstImage1);
imshow("【效果图二】", dstImage2);
waitKey(0);
return 0;
}
运行结果:原始图 / 效果图一 / 效果图二
1、向上采样:pyrUp()函数
pyrUp()函数向上采样并模糊一张图像,即放大一张图片;
源码溯源:(位于..\opencv\sources\modules\imgproc\src\pyramids.cpp中)
void cv::pyrUp( InputArray _src,
OutputArray _dst,
const Size& _dsz,
int borderType )
{
CV_INSTRUMENT_REGION()
CV_Assert(borderType == BORDER_DEFAULT);
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
ocl_pyrUp(_src, _dst, _dsz, borderType))
Mat src = _src.getMat();
Size dsz = _dsz.area() == 0 ? Size(src.cols*2, src.rows*2) : _dsz;
_dst.create( dsz, src.type() );
Mat dst = _dst.getMat();
int depth = src.depth();
#ifdef HAVE_TEGRA_OPTIMIZATION
if(borderType == BORDER_DEFAULT && tegra::useTegra() && tegra::pyrUp(src, dst))
return;
#endif
#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()*2, _src.rows()*2),
ipp_pyrup( _src, _dst, _dsz, borderType));
PyrFunc func = 0;
if( depth == CV_8U )
func = pyrUp_, PyrUpVec_32s8u >;
else if( depth == CV_16S )
func = pyrUp_, PyrUpVec_32s16s >;
else if( depth == CV_16U )
func = pyrUp_, PyrUpVec_32s16u >;
else if( depth == CV_32F )
func = pyrUp_, PyrUpVec_32f >;
else if( depth == CV_64F )
func = pyrUp_, PyrUpNoVec >;
else
CV_Error( CV_StsUnsupportedFormat, "" );
func( src, dst, borderType );
}
源码简版:
void cv::pyrUp( InputArray _src,
OutputArray _dst,
const Size& _dsz = SIze(),
int borderType = BORDER_DEFAULT )
参数解析:
pyrUp函数执行高斯金字塔的采样操作,其实也可用拉普拉斯金字塔的。
First,它通过插入可为零的行与列,对源图像进行向上采样操作,
then,将结果与pyrDown()乘以4的内核做卷积。
<2>pyrUp函数简单示例:
#include
using namespace cv;
int main() {
//载入原图
Mat srcImage = imread("1.jpg");
Mat temImage, dstImage;//临时变量和目标图的定义
temImage = srcImage;
//显示原图
imshow("【原始图】", srcImage);
//进行向上采样操作
pyrUp(temImage, dstImage, Size(temImage.cols * 2, temImage.rows * 2));
//显示效果图
imshow("效果图", dstImage);
waitKey(0);
return 0;
}
运行结果:
2、向下采样:pyrDown()函数
pyrDown()函数用来向下采样并模糊一张图片,即缩小一张图片。
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.area() == 0 ? 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_TEGRA_OPTIMIZATION
if(borderType == BORDER_DEFAULT && tegra::useTegra() && tegra::pyrDown(src, dst))
return;
#endif
#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_, PyrDownVec_32s8u>;
else if( depth == CV_16S )
func = pyrDown_, PyrDownVec_32s16s >;
else if( depth == CV_16U )
func = pyrDown_, PyrDownVec_32s16u >;
else if( depth == CV_32F )
func = pyrDown_, PyrDownVec_32f>;
else if( depth == CV_64F )
func = pyrDown_, PyrDownNoVec >;
else
CV_Error( CV_StsUnsupportedFormat, "" );
func( src, dst, borderType );
}
源码简版:
void cv::pyrDown( InputArray _src,
OutputArray _dst,
const Size& _dsz = Size(),
int borderType = BORDER_DEFAUT )
参数解析:
该pyrDown()函数执行了高斯金字塔建筑,首先,它将源图像与如下内核做卷积运算:
接着,它便通过对图像的偶数行和列做插值来进行向下采样操作。
<2>pyrDown()函数简单示例:
#include
using namespace cv;
int main() {
//载入原图
Mat srcImage = imread("1.jpg");
Mat temImage, dstImage;//临时变量和目标图的定义
temImage = srcImage;
//显示原图
imshow("【原始图】", srcImage);
//进行向下采样操作
pyrDown(temImage, dstImage, Size(temImage.cols / 2, temImage.rows / 2));
//显示效果图
imshow("效果图", dstImage);
waitKey(0);
return 0;
}
运行结果:
#include
using namespace std;
using namespace cv;
#define WINDOW_NAME "【程序窗口】"
Mat g_srcImage, g_dstImage, g_tmpImage;
int main() {
g_srcImage = imread("1.jpg");
if (!g_srcImage.data) {
printf("读取g_srcImage错误!\n");
return false;
}
//创建显示窗口
namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);
imshow(WINDOW_NAME, g_srcImage);//显示原图
//参数设置
g_tmpImage = g_srcImage;
g_dstImage = g_tmpImage;
int key = 0;
//轮询获取案件信息
while (1) {
key = waitKey(9);//读取键值到key变量中
switch (key) {//用1、2、3、4、w、s、a、d来控制图片缩放
case 27://按下ESC
case 'q':
return 0;
break;
case 'a'://按下a键,调用pyrUp函数
pyrUp(g_tmpImage, g_dstImage, Size(g_tmpImage.cols * 2, g_tmpImage.rows * 2));
printf(">检测到按键A被按下,开始基于pyrUp函数的图片放大\n");
break;
case 'w'://w被按下,调用resize函数
resize(g_tmpImage, g_dstImage, Size(g_tmpImage.cols * 2, g_tmpImage.rows * 2));
printf(">检测到按键W被按下,开始基于resize函数的放大\n");
break;
case '1'://按下按键1,调用resize函数
resize(g_tmpImage, g_dstImage, Size(g_tmpImage.cols * 2, g_tmpImage.rows * 2));
printf(">检测到按键1被按下,开始基于resize函数的放大\n");
break;
case '3'://按键3被按下,调用pyrUp函数
pyrUp(g_tmpImage, g_dstImage, Size(g_tmpImage.cols * 2, g_tmpImage.rows * 2));
printf(">检测到按键3被按下,开始基于pyrUp函数的图片放大\n");
break;
case 'd'://按下按键D,调用pyrDown函数
pyrDown(g_tmpImage, g_dstImage, Size(g_tmpImage.cols / 2, g_tmpImage.rows / 2));
printf(">检测到按键D被按下,开始基于pyrDown函数的图片缩小\n");
break;
case 's':
resize(g_tmpImage, g_dstImage, Size(g_tmpImage.cols / 2, g_tmpImage.rows / 2));
printf(">检测到按键S被按下,开始基于resize函数的缩小\n");
break;
case '2'://按键2被按下,调用resize函数
resize(g_tmpImage, g_dstImage, Size(g_tmpImage.cols / 2, g_tmpImage.rows / 2),(0,0),(0,0),0);
printf(">检测到按键2被按下,开始基于resize函数的缩小\n");
break;
case '4'://按键4被按下,调用pyrDown函数
pyrDown(g_tmpImage, g_dstImage, Size(g_tmpImage.cols / 2, g_tmpImage.rows / 2));
printf(">检测到按键4被按下,开始基于pyrDown函数的缩小\n");
break;
}
//经过操作后,显示变化后的图片
imshow(WINDOW_NAME, g_dstImage);
//将g_dstImage赋给g_tmpImage,以便于下一次循环
g_tmpImage = g_dstImage;
}
return 0;
}
运行截图: