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

参考文章:
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

相关推荐
Boop_wu24 分钟前
[Java EE] 多线程 -- 初阶(1)
java·jvm·算法
陌路2039 分钟前
Linux33 网络编程-多线程TCP并发
网络·算法
骄傲的心别枯萎3 小时前
RV1126 NO.37:OPENCV的图像叠加功能
人工智能·opencv·计算机视觉·音视频·视频编解码·rv1126
这张生成的图像能检测吗6 小时前
(论文速读)Fast3R:在一个向前通道中实现1000+图像的3D重建
人工智能·深度学习·计算机视觉·3d重建
心 爱心 爱6 小时前
Shape-Guided Dual-Memory Learning for 3D Anomaly Detection 论文精读
计算机视觉·3d·异常检测·工业异常检测·三维异常检测·多模态工业异常检测·二维异常检测
星释8 小时前
Rust 练习册 :Pythagorean Triplet与数学算法
开发语言·算法·rust
星释8 小时前
Rust 练习册 :Nth Prime与素数算法
开发语言·算法·rust
多喝开水少熬夜9 小时前
Trie树相关算法题java实现
java·开发语言·算法
WBluuue9 小时前
数据结构与算法:树上倍增与LCA
数据结构·c++·算法
bruk_spp10 小时前
牛客网华为在线编程题
算法