Ubuntu系统VScode实现opencv(c++)图像放缩与插值
在图像处理与计算机视觉任务中,图像的尺寸调整(即图像放大与缩小)是一项基础而关键的操作。由于图像在分辨率变化时像素点无法一一对应,必须通过插值方法估算新的像素值,以尽可能保留图像的结构与细节。插值方法的选择直接影响到图像缩放后的质量与计算效率。常见的插值策略包括最近邻插值(Nearest Neighbor)、双线性插值(Bilinear Interpolation)、双三次插值(Bicubic Interpolation)以及基于区域或窗函数的高阶插值方法(如 Lanczos)。其中,不同插值方法在重建精度、边缘保留能力与运算复杂度之间存在权衡,因此需要根据具体应用场景合理选取。
插值方法原理与运算方式
下面是常见插值方法的原理、计算公式和区别:
1. 最近邻插值(Nearest Neighbor)
原理:选择距离目标像素最近的一个原始像素,直接赋值。
公式:
特点:非常快,图像边缘锯齿明显,无平滑过渡。
2. 双线性插值(Bilinear Interpolation)
原理:在目标点周围找到2×2个像素点,先在x轴方向线性插值,然后在y轴方向再插一次。
公式:
特点:平滑过渡,速度快,效果一般,常用于视频播放、实时处理等场景。
3. 双三次插值(Bicubic Interpolation)
原理:使用周围 4×4 = 16 个像素点参与计算,使用三次多项式(立方插值)进行加权平均。
公式:三次插值的一般形式:
整体过程:
先在x轴方向上对每一行进行三次插值(得到4个值)。
然后对这4个值在y轴方向再插一次。
特点:效果更细腻,边缘更平滑,计算较慢,常用于图像编辑软件(如PS)。
4. 区域插值(Area)
原理:缩小时,把多个像素平均成一个区域的像素(防止别 aliasing 伪影)。
计算方式:对所有被合并区域的像素求加权平均:
特点:适合缩小图像时使用,保留图像整体亮度和颜色。
5. Lanczos 插值
原理:使用 sinc函数(sin(πx)/(πx)) 的加权和来进行高精度插值(窗口大小通常为3或5)
公式(简化):
特点:质量最好(适合摄影放大),运算最复杂,用于离线处理、高质量图像缩放。
插值方式总结
方法 | 使用点数 | 质量 | 运算复杂度 | 适合场景 |
---|---|---|---|---|
INTER_NEAREST( 最近邻) | 1 | 差 | 最快 | 实时预览、图像分割 |
INTER_LINEAR :双线性(默认) | 4 | 中 | 快 | 视频处理、通用缩放 |
INTER_CUBIC :双三次(适合放大) | 16 | 好 | 中-慢 | 图像编辑、照片放大 |
INTER_AREA :区域插值(适合缩小) | 多 | 中等 | 中 | 图像缩小 |
INTER_LANCZOS4 :Lanczos 插值 | 多 | 最好 | 慢 | 摄影图、医学图像处理 |
相关函数介绍:
void cv::resize(InputArray src,OutputArray dst,Size dsize,double fx = 0,double fy = 0,int interpolation = INTER_LINEAR
);
参数 | 说明 |
---|---|
src | 输入图像(cv::Mat 类型) |
dst | 输出图像(缩放后的图像) |
dsize | 输出图像的大小(cv::Size(width, height) )。若为 (0, 0) ,则必须提供 fx 和 fy 。 |
fx | 水平方向缩放因子(相对于原图宽度) |
fy | 垂直方向缩放因子(相对于原图高度) |
interpolation | 插值方法,决定如何估算目标图像的像素值(见下方说明) |
放缩的方式有两种:
1.指定目标大小缩
Size(width, height),直接指定放缩后的宽高;
2.指定缩放因子
给定fx,fy,即可放缩。
void Demo::Resize_Demo(Mat &image)
{Mat zoomin,zoomin1;int h = image.rows;int w = image.cols;cout<<"宽:"<<w<<",高:"<<h<<endl;resize(image,zoomin,Size(256,256),0,0,INTER_LINEAR);resize(image,zoomin1,Size(),0.5,0.5,INTER_LINEAR);imshow("zoomin",zoomin);cout<<"zoomin宽:"<<zoomin.cols<<",zoomin高:"<<zoomin.rows<<endl;imshow("zoomin1",zoomin1);cout<<"zoomin1宽:"<<zoomin1.cols<<",zoomin1高:"<<zoomin1.rows<<endl;
}
这里我们打印一下相应图片的宽高,检验是否放缩正确:
这里采用的是最常规的线性放缩,其他插值方式可以自己比较一下区别。