【图像处理】常见图像插值算法与应用

参考文章:
https://blog.csdn.net/Datawhale/article/details/105697264

一、常见插值算法

1.1 最近邻插值算法

原理简介

将目标图像像素映射到原图像后,取距离最近的整数坐标像素值作为该像素的输出值。

例如 :目标图像某点投影到原图像的位置为P,与P距离最近的点为Q11,则该点像素值 f(P) = f(Q11)

例子说明

将3×3原图像(用f(x,y)表示)放大到4×4目标图像(用h(x,y)表示),映射公式如下:

缺点
  • 放大图像会出现明显马赛克/块状效应
  • 缩小图像会产生严重失真

本质是目标像素仅由原图像单个像素决定,未考虑周围像素的影响。

1.2 双线性插值算法

双线性插值是线性插值在二维空间的推广,通过3次线性插值(X方向2次、Y方向1次),用周围4个像素的加权值确定目标像素,效果更平滑。

1. 线性插值基础

线性插值通过连接两个已知量的直线,计算两者之间未知量的值,公式如下:

f ( x ) = a 1 x + a 0 f(x) = a_1x+a_0 f(x)=a1x+a0

线性插值多项式:

插值余项(误差):

函数曲率越大,插值误差越大。

2. 双线性插值步骤

假设已知原图像中4个点 f(x0,y0)、f(x1,y1)、f(x0,y1)、f(x1,y0) 的值,目标是计算这4个点构成的矩形内任意点 f(x,y) 的值:

  1. X方向两次线性插值 :分别计算y0和y1行上x处的插值结果

  2. Y方向一次线性插值 :用X方向的两个结果计算y处的最终值

综合公式:

若4个点为单位正方形顶点(坐标(0,0)、(0,1)、(1,0)、(1,1)),公式可简化为:

3. 原图像与目标图像的几何中心对齐

直接映射会导致原图像部分像素未参与计算(如9×9缩小到3×3时,右下角像素未被使用),需添加调节因子使两者中心对齐,OpenCV默认采用此方式。

  • 普通映射公式:

  • 中心对齐映射公式(添加调节因子 0.5*(src_width/dst_width - 1)):

4. OpenCV中cv.resize()的计算逻辑

根据目标像素在原图像中的位置,分三种情况处理:

  • 中间点:正常双线性插值(取周围4个点)
  • 边界点(非顶点):线性插值(如目标点映射到原图像外时,取最近两个点)
  • 四个顶点:最近邻插值(直接取原图像顶点值)

计算示例(3×3原图像放大到4×4):

  • 中间点公式:
  • 边界点公式:

  • 顶点公式:

2.3 三次样条插值算法

三次样条插值通过分段三次多项式拟合原图像像素,满足"连续可导"条件,插值效果更平滑,但计算复杂度更高。

核心思想

给定n+1个点 a=x0<x1<...<xn=b 及对应函数值 f(xi),在每个区间 [xi, xi+1] 构造三次多项式 Si(x) = aix³ + bix² + cix + di,需满足4n个条件:

  1. 插值条件:Si(xi) = f(xi)Si(xi+1) = f(xi+1)(共2n个)
  2. 连续可导条件:Si'(xi+1) = Si+1'(xi+1)Si''(xi+1) = Si+1''(xi+1)(共2n-2个)
  3. 边界条件(3选1):
    • 自然边界:S0''(x0) = 0Sn-1''(xn) = 0
    • 一阶导数已知:S0'(x0) = f'(x0)Sn-1'(xn) = f'(xn)
    • 周期边界:S0'(x0) = Sn-1'(xn)S0''(x0) = Sn-1''(xn)

通过求解4n个方程组,得到每个多项式的系数,最终计算目标像素值。

三、两种映射方法

图像几何变换的本质是像素坐标映射,分为向前映射和向后映射两种方式。

3.1 向前映射(像素移交映射)

过程
  1. 坐标变换 :由原图像像素坐标 (x,y) 推算其在目标图像的坐标 (x',y')(通常为非整数)。
  2. 像素分配 :将原图像像素值按权重分配给目标图像中 (x',y') 周围的4个整数坐标点。
缺点
  • 目标图像像素值需叠加多个原图像像素的分配权重,需额外记录权重总和并归一化。
  • 可能出现目标图像"漏点"(部分像素未被分配到值)。

3.2 向后映射(像素填充算法)

过程
  1. 坐标变换 :由目标图像像素坐标 (x',y') 反推其在原图像的坐标 (x,y)(通常为非整数)。
  2. 插值计算 :通过最近邻、双线性等插值算法,用原图像中 (x,y) 周围的像素值计算目标像素值。
优点
  • 每个目标像素仅需一次插值计算,无需遍历所有原图像像素。
  • 无"漏点"问题,是主流的映射方式(前文插值算法均基于向后映射)。

四、动手实现(基于OpenCV)

OpenCV的cv.resize()函数支持多种插值方式,可直接用于图像缩放,以下是C++和Python的实现示例。

4.1 C++实现

1. cv.resize()函数原型

cpp 复制代码
void cv::resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR);

参数说明:

参数 含义
src 输入原图像
dst 输出目标图像
dsize 目标图像尺寸(Size(cols, rows),cols为列数,rows为行数)
fx/fy 水平/垂直方向的缩放因子(dsize为None时生效)
interpolation 插值方式(默认双线性插值INTER_LINEAR)

2. 常用插值方式

插值方式 说明 适用场景
INTER_NEAREST 最近邻插值 速度快,对精度要求低的场景
INTER_LINEAR 双线性插值(默认) 放大/缩小,平衡速度与效果
INTER_CUBIC 三次样条插值 放大图像,追求高平滑度
INTER_AREA 区域插值 缩小图像,减少失真

3. 完整代码

cpp 复制代码
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
    // 读取原图像(需替换为你的图像路径)
    Mat img = imread("C:/Users/94890/Desktop/picture/luelue.jpg");
    if (img.empty())
    {
        cout << "无法读取图像" << endl;
        return 0;
    }

    // 获取原图像尺寸
    int height = img.rows;  // 行数(垂直方向)
    int width = img.cols;   // 列数(水平方向)

    // 1. 缩小图像(0.2倍,双线性插值)
    Size dsize_shrink = Size(round(0.2 * width), round(0.2 * height));
    Mat shrink;
    resize(img, shrink, dsize_shrink, 0, 0, INTER_LINEAR);

    // 2. 放大图像(在缩小图像基础上放大1.5倍,对比两种插值)
    float fx = 1.5, fy = 1.5;
    Mat enlarge_nearest, enlarge_linear;
    resize(shrink, enlarge_nearest, Size(), fx, fy, INTER_NEAREST);  // 最近邻插值
    resize(shrink, enlarge_linear, Size(), fx, fy, INTER_LINEAR);    // 双线性插值

    // 显示图像
    imshow("原图像", img);
    imshow("0.2倍缩小(双线性)", shrink);
    imshow("1.5倍放大(最近邻)", enlarge_nearest);
    imshow("1.5倍放大(双线性)", enlarge_linear);

    // 保存图像
    imwrite("C:/Users/94890/Desktop/picture/shrink2.jpg", shrink);
    imwrite("C:/Users/94890/Desktop/picture/INTER_NEAREST2.jpg", enlarge_nearest);
    imwrite("C:/Users/94890/Desktop/picture/INTER_LINEAR2.jpg", enlarge_linear);

    waitKey(0);  // 等待按键关闭窗口
    destroyAllWindows();
    return 0;
}

4. 实验结果

  • 原图像:
  • 0.2倍缩小(双线性):
  • 1.5倍放大(最近邻):
  • 1.5倍放大(双线性):

更多资料:https://github.com/0voice

相关推荐
夜晚中的人海4 小时前
【C++】使用双指针算法习题
开发语言·c++·算法
im_AMBER6 小时前
数据结构 06 线性结构
数据结构·学习·算法
earthzhang20218 小时前
【1028】字符菱形
c语言·开发语言·数据结构·c++·算法·青少年编程
papership8 小时前
【入门级-算法-3、基础算法:二分法】
数据结构·算法
通信小呆呆8 小时前
收发分离多基地雷达椭圆联合定位:原理、算法与误差分析
算法·目标检测·信息与通信·信号处理
CV实验室10 小时前
TIP 2025 | 哈工大&哈佛等提出 TripleMixer:攻克雨雪雾干扰的3D点云去噪网络!
人工智能·计算机视觉·3d·论文
丁浩66612 小时前
Python机器学习---2.算法:逻辑回归
python·算法·机器学习
伏小白白白12 小时前
【论文精度-2】求解车辆路径问题的神经组合优化算法:综合展望(Yubin Xiao,2025)
人工智能·算法·机器学习
应用市场12 小时前
OpenCV编程入门:从零开始的计算机视觉之旅
人工智能·opencv·计算机视觉