图像缩放是图像处理中的基础操作之一。无论是图像预处理、数据增强还是图像金字塔构建,cv::resize
都是我们最常用的函数之一。但你是否注意到,在 OpenCV 中同时还存在一个名为 cv::Mat::resize
的方法?这两个函数虽然名字类似,但用途完全不同。
本篇博客将系统介绍 cv::resize
的功能与使用方法,并重点提示开发者不要将其与 cv::Mat::resize
混淆。
cv::resize
:图像尺寸缩放
void cv::resize(
InputArray src,
OutputArray dst,
Size dsize,
double fx = 0,
double fy = 0,
int interpolation = INTER_LINEAR
);
- src: 输入图像
- dst: 输出图像
- dsize,fx,fy: 输出图像尺寸,可以使用dsize明确指出输出图像尺寸(如cv::Size(100,100)),或者使用fx,fy分别控制水平与垂直方向上缩放系数,如fx=0.5表示水平方向上缩小到原尺寸的0.5
- interpolation: 插值方式,包括:
INTER_NEAREST
最近邻,INTER_LINEAR
双线性(默认),INTER_CUBIC
双三次,INTER_AREA
像素区域重采样(适合缩小)
cv::Mat img = cv::imread("lena.jpg");
cv::Mat small, large, dst;
// 缩小为原来一半
cv::resize(img, small, cv::Size(), 0.5, 0.5, cv::INTER_AREA);
// 放大到原图2倍
cv::resize(img, large, cv::Size(), 2.0, 2.0, cv::INTER_CUBIC);
// 变换到指定尺寸
// 注意:目标尺寸的指定方法只能二选一,如选择指定尺寸则缩放系数为0,反之指定尺寸为0
cv::resize(img, dst, cv::Size(100, 100), 0, 0, cv::INTER_CUBIC);
不同插值方式的比较
插值方法 | 缩小时效果 | 放大时效果 | 说明 |
---|---|---|---|
INTER_NEAREST | 锯齿明显 | 像素块状 | 最快但最差 |
INTER_LINEAR | 较平滑 | 较清晰 | 适合放大,缩小时推荐平滑图像后调用 |
INTER_CUBIC | 非常平滑 | 较锐利 | 适合放大,缩小时推荐平滑图像后调用 |
INTER_AREA | 保细节 | 效果一般 | 专门为缩小图像设计,等价于平滑图像+INTER_LINEAR |
常见误区:不要把 cv::resize
和 cv::Mat::resize
混淆
OpenCV 中还有另一个方法 cv::Mat::resize(size_t)
,这个函数并不是用于图像缩放,而是改变矩阵中的元素数量。举例说明:
// 创建一个1行10列的矩阵(或向量)
cv::Mat vec = (cv::Mat_<int>(1, 10) << 1,2,3,4,5,6,7,8,9,10);
// 仅保留前5个元素
// 这里通过改变Mat对象头文件实现数据尺寸改变,
// 如果改变后尺寸大于原来尺寸可能进行内存分布,否则不会进行内存分配!
vec.resize(5); // 注意:这不是图像缩小!
一句话总结:图像缩放用 cv::resize
,向量裁剪才 Mat::resize。
实用技巧
图像缩小建议使用
INTER_AREA
当你对图像进行缩小时,INTER_AREA
的区域重采样方法可以保留更多细节,避免马赛克感。
cv::resize(img, small, cv::Size(), 0.25, 0.25, cv::INTER_AREA);
- 你也可以使用固定目标尺寸进行缩放,不依赖缩放因子。
cv::resize(img, resized, cv::Size(256, 256)); // 直接缩放到 256×256
- 在一些应用中存在批量图像缩放到统一尺寸的需求,常见用法如下:
std::vector<cv::Mat> images = ...;
for (auto& img : images) {
cv::resize(img, img, cv::Size(224, 224));
}
深入理解图像缩放
在深入理解图像插值:从原理到应用中,我们对与resize相关的图像插值进行了详细的讲解,您可以参考该博文以深入理解图像缩放相关内容。