图像的放大:双三次插值算法(C++实现)

article/2025/9/23 15:11:20

双线性插值算法的不足就是细节处理的不好,换句话说,就是曲线拟合得不够光滑,所以又有了双三次插值算法。双三次插值算法是基于周围的16个像素点,通过计算16个像素点的权重,累积得到增加点的像素值的。
在这里插入图片描述
简单点理解,公式如下:
p = f ( u , v ) = ∑ i = 0 3 ∑ j = 0 3 w i j x i y j p=f(u,v)=\sum_{i=0}^{3}\sum_{j=0}^{3}w_{ij}x_{i}y_{j} p=f(u,v)=i=03j=03wijxiyj
(u,v)为所插入点的坐标,(x,y)为周围16个像素点的坐标。本算法的重点和难点就是权重w的值如何获取。我们取其中的x方向(横轴)分析, w x i w_{xi} wxi的取值如下公式所示:
w x i = { ( a + 2 ) ∣ x i − u ∣ 3 − ( a + 3 ) ∣ x i − u ∣ 2 + 1 f o r ∣ x i − u ∣ ≤ 1 a ∣ x i − u ∣ 3 − 5 a ∣ x i − u ∣ 2 + 8 a ∣ x i − u ∣ − 4 a f o r 1 < ∣ x i − u ∣ < 2 0 o t h e r w i s e w_{xi}=\left\{\begin{matrix} (a+2)\left | x_i-u \right |^{3}-(a+3)\left | x_i-u \right |^{2}+1 & for & \left | x_i-u \right |\leq 1\\ a\left | x_i-u \right |^{3}-5a\left | x_i-u \right |^{2}+8a\left | x_i-u \right |-4a & for &1< \left | x_i-u \right |< 2 \\ 0 &otherwise \end{matrix}\right. wxi=(a+2)xiu3(a+3)xiu2+1axiu35axiu2+8axiu4a0forforotherwisexiu11<xiu<2
同理,也可以得到 w y j w_{yj} wyj,则可以得到权重的表达式如下公式所示:
w i j = w x i × w y j w_{ij}=w_{xi}\times w_{yj} wij=wxi×wyj
c++代码实现:
"bmp.h"的头文件代码:bmp图片的类以及读写函数 bmp.h

#include <iostream>
#include <string.h>   
#include <math.h>       
#include <stdlib.h>     
#include <malloc.h>  
#include <cstdio>
#include "bmp.h"
using namespace std;
#define DRAW_HEIGHT 512  //目标图像高度  
#define DRAW_WIDTH 512  //目标图像宽度  
double a=-0.5; //BiCubic基函数void getW_x(double w_x[4],double x);
void getW_y(double w_y[4], double y);int main()
{BMP rbmp;BMP wbmp(DRAW_WIDTH,DRAW_HEIGHT);char strFile[50] = "./lena24.bmp";//打开图像路径,BMP图像必须为24位真彩色格式  char strFilesave[50] = "./test.bmp";//处理后图像存储路径 //读取位图的数据 imread(strFile,rbmp);int width = rbmp.cols();int height = rbmp.rows(); int l_width = WIDTHBYTES(width*24);//计算位图的实际宽度并确保它为4byte的倍数  //写位图的数据int write_width = WIDTHBYTES(DRAW_WIDTH*24);//计算写位图的实际宽度(字节)并确保它为4byte的倍数   /*******************图像处理部分******************/for (int hnum = 2; hnum < DRAW_HEIGHT-4; hnum++){for (int wnum = 2; wnum < DRAW_WIDTH-4; wnum++){double d_original_img_hnum = hnum*height / (double)DRAW_HEIGHT;double d_original_img_wnum = wnum*width / (double)DRAW_WIDTH;int i_original_img_hnum = d_original_img_hnum;//距离最近的点坐标int i_original_img_wnum = d_original_img_wnum;//距离最近的点坐标double w_x[4], w_y[4];//行列方向的加权系数getW_x(w_x, d_original_img_hnum);getW_y(w_y, d_original_img_wnum);int pixel_point = hnum*write_width + wnum * 3;//映射尺度变换图像数组位置偏移量  for(int i=0;i<4;i++){for(int j=0;j<4;j++){int original_point=(i_original_img_hnum+i-1)*l_width + (i_original_img_wnum+j-1)*3;wbmp.pColorData[pixel_point]+=rbmp.pColorData[original_point]*w_x[i]*w_y[j];wbmp.pColorData[pixel_point + 1]+=rbmp.pColorData[original_point+1]*w_x[i]*w_y[j];wbmp.pColorData[pixel_point + 2]+=rbmp.pColorData[original_point+2]*w_x[i]*w_y[j];}}}}/*******************图像处理部分******************/std::cout<<"Done!"<<std::endl;imwrite(strFilesave,wbmp); system("pause"); return 0;
}
/*计算系数*/
void getW_x(double w_x[4],double x){int X = (int)x;//取整数部分double stemp_x[4];stemp_x[0] = 1 + (x - X);stemp_x[1] = x - X;stemp_x[2] = 1 - (x - X);stemp_x[3] = 2 - (x - X);w_x[0] = a*abs(stemp_x[0] * stemp_x[0] * stemp_x[0]) - 5 * a*stemp_x[0] * stemp_x[0] + 8 * a*abs(stemp_x[0]) - 4 * a;w_x[1] = (a + 2)*abs(stemp_x[1] * stemp_x[1] * stemp_x[1]) - (a + 3)*stemp_x[1] * stemp_x[1] + 1;w_x[2] = (a + 2)*abs(stemp_x[2] * stemp_x[2] * stemp_x[2]) - (a + 3)*stemp_x[2] * stemp_x[2] + 1;w_x[3] = a*abs(stemp_x[3] * stemp_x[3] * stemp_x[3]) - 5 * a*stemp_x[3] * stemp_x[3] + 8 * a*abs(stemp_x[3]) - 4 * a;
}
void getW_y(double w_y[4], double y){int Y = (int)y;double stemp_y[4];stemp_y[0] = 1.0 + (y - Y);stemp_y[1] = y - Y;stemp_y[2] = 1 - (y - Y);stemp_y[3] = 2 - (y - Y);w_y[0] = a*abs(stemp_y[0] * stemp_y[0] * stemp_y[0]) - 5 * a*stemp_y[0] * stemp_y[0] + 8 * a*abs(stemp_y[0]) - 4 * a;w_y[1] = (a + 2)*abs(stemp_y[1] * stemp_y[1] * stemp_y[1]) - (a + 3)*stemp_y[1] * stemp_y[1] + 1;w_y[2] = (a + 2)*abs(stemp_y[2] * stemp_y[2] * stemp_y[2]) - (a + 3)*stemp_y[2] * stemp_y[2] + 1;w_y[3] = a*abs(stemp_y[3] * stemp_y[3] * stemp_y[3]) - 5 * a*stemp_y[3] * stemp_y[3] + 8 * a*abs(stemp_y[3]) - 4 * a;
}

效果图:
在这里插入图片描述
在这里插入图片描述
参考:图像缩放之双三次插值法


http://chatgpt.dhexx.cn/article/lGTUiN56.shtml

相关文章

图像插值理论研究——双三次插值(双立方插值)

双三次插值&#xff0c;英文是Bicubic interpolation。双三次插值是一种更加复杂的插值方式&#xff0c;它能创造出比双线性插值更平滑的图像边缘。双三次插值方法通常运用在一部分图像处理软件、打印机驱动程序和数码相机中&#xff0c;对原图像或原图像的某些区域进行放大。A…

FPGA图像处理HLS实现三种图像缩放算法,线性插值、双线性插值、双三次插值,提供HLS工程和vivado工程源码

目录 一、三种图像缩放算法介绍线性插值双线性插值双三次插值 二、HLS实现线性插值图像缩放三、HLS实现双线性插值图像缩放四、HLS实现双三次插值图像缩放五、HLS在线仿真并导出IP六、其他FPGA型号HLS在线仿真并导出IP七、zynq7100开发板vivado工程八、上板调试验证九、福利&am…

数字图像处理100问—27 双三次插值( Bicubic Interpolation )

提示&#xff1a;内容整理自&#xff1a;https://github.com/gzr2017/ImageProcessing100Wen CV小白从0开始学数字图像处理 27 双三次插值&#xff08; Bicubic Interpolation &#xff09; 使用双三次插值将图像放大1.5倍 双三次插值是双线性插值的扩展&#xff0c;使用邻域…

用于数字成像的双三次插值技术​

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶” 重磅干货&#xff0c;第一时间送达 双三次插值是使用三次或其他多项式技术的2D系统&#xff0c;通常用于锐化和放大数字图像。在图像放大、重新采样时&#xff0c;或是在软件中润饰和编辑图像时也会使到用…

插值算法(最邻近差值、双线性插值、双三次插值)

一、最邻近差值&#xff08;nearest&#xff09; 含义&#xff1a; 选取离目标点最近的点的值作为新的插入点的值。 两幅图坐标值变换关系&#xff1a; &#xff08;代码未验证&#xff09; for i1:size(dist,1)x round(i* (size(src,1)/size(dist,1))); %dst横坐标变换到s…

matlab双线性插值双三次插值对CUFED5进行处理

本文是摘抄与总结&#xff0c;仅供自己学习和日后查阅使用。 可以自己写一个双线性插值函数&#xff0c; ------------------------------------------------------------------- function outputimg my_imresize(A,n) % A 是图像矩阵,n是放缩的倍数 % 返回值outputimg是一…

双三次插值算法的C++实现与SSE指令优化

在上篇文章中&#xff0c;我们讲解了常见的最邻近插值算法、双线性插值算法和双三次插值算法的原理与实现&#xff0c;三种插值算法中双三次插值算法的插值效果最好&#xff0c;但其也是三种算法中计算复杂度最高、耗时最长的算法。本文在给出双三次插值C代码的基础上&#xff…

双三次插值 - 插值图像任意位置亚像素C++

双三次插值 - 插值图像任意位置亚像素C 一、概念 双三次插值又称立方卷积插值。三次卷积插值是一种更加复杂的插值方式。该算法利用待采样点周围16个点的灰度值作三次插值&#xff0c;不仅考虑到4 个直接相邻点的灰度影响&#xff0c;而且考虑到各邻点间灰度值变化率的影响。…

matlab 给图像双三次,图像灰度的双三次插值的MATLAB实现

相比C/C实现&#xff0c;图像灰度的双三次插值的MATLAB实现要方便的多&#xff0c;下面是MATLAB语言实现 clc,clear; ffimread(C:\Program Files\MATLAB\R2013a\bin\work\lena.bmp); [mm,nn]size(ff);%将图像隔行隔列抽取元素&#xff0c;得到缩小的图像f mmm/2;nnn/2; fzeros(…

java 双三次线性插值_三种常见的图像处理双三次插值算法

三种常见的图像处理双三次插值算法 双立方插值计算涉及16像素,间(i’, j’)像中的包括 小数部分的像素坐标。dx表示X方向的小数坐标。dy表示Y方向的小数坐标。 详细 能够看下图: 依据上述图示与双立方插值的数学表达式能够看出。双立方插值本质上图像16个像素点 权重卷积之和…

双三次插值 python实现_Python:用GPU实现双三次插值

它不是GPU(而是尝试利用线程和CPU的向量单元)&#xff0c;但是pyvips比scipy快很多&#xff0c;您可以测试一下。在 我做了个基准&#xff1a;import sys import time import scipy.ndimage import pyvips scale 10 n_loops 10 start time.time() test_image scipy.ndimage…

双三次插值及Matlab实现

双三次插值及Matlab实现 一、简单实例 采用简单实例进行对双三次插值的介绍&#xff0c;由于双三次插值对于目标图像的某一像素进行估计时&#xff0c;所采用的像素信息为其周围16个像素点信息&#xff0c;因此不同于最近邻插值和双线性插值&#xff0c;此时假设有 5 5 5\tim…

【opencv】最近邻插值、双线性插值、双三次插值(三次样条插值)

目录 1. 最近邻插值2. 双线性插值1&#xff09;简单理解2&#xff09;一般性 3. 双三次插值&#xff08;三次样条插值&#xff09;总结 b站 视频讲解 &#xff1a; https://www.bilibili.com/video/BV1wh411E7j9/ 1. 最近邻插值 举个简单例子&#xff1a;一个 3 3 3 \times 3…

挑战图像处理100问(27)——双三次插值

当我们需要对图像进行放大或缩小时&#xff0c;为了避免图像变形或失真&#xff0c;我们需要进行插值。插值是一种基于已知数据点&#xff0c;在这些数据点之间进行估计的方法。在图像处理中&#xff0c;常见的插值方法包括最邻近插值、双线性插值、双三次插值等。 双三次插值…

【图像超分辨(SR)】通俗直观彻底理解双线性插值、双三次插值及其作用

写在前面的一点话 网上讲解基本双线性插值、双三次线性插值的文章很多&#xff0c;但大部分都是只在讲为什么是这样&#xff0c;并不算非常通俗&#xff08;起码对我来说需要额外查很多资料来补充理解&#xff09;。很少有文章能够给初学者一些比较直观的理解&#xff0c;因此…

插值法(最邻近,双线性,双三次)的原理及实现

插值法(最邻近&#xff0c;双线性&#xff0c;双三次&#xff09;的原理及实现 常用的插值方法有最邻近插值法、双现象插值法和双三次插值法等&#xff0c;主要用于图像的放大或缩小。 缩小图像&#xff08;或称为下采样&#xff08;subsampled&#xff09; 或降采样&#xf…

表示关系x =y =z的c语言表达式为________.,为表示关系x≥y≥z,应使用C语言表达式____。...

为表焦距决定了画面的透视关系。 示关使用GREGRE ≥y≥桡神经沟位于 应C语言表关于脊柱正确的描写是() 建筑物或者其他设施以及建筑物上的搁置物、达式悬挂物发生( )造成他人损害的&#xff0c;所有人或者管理人应当承担民事责任,但能够证明自己没有过错的除外。 为表成对的脑颅…

C语言运算表达式整理

C语言的运算规则是按照运算符的优先级进行的&#xff0c;所以我们首先看一下C的运算优先级别 总结 最简单的优先级就是 算数运算符>关系运算符>逻辑运算符>赋值运算符 然后我们还要了解一个短路规则&#xff08;特性&#xff09; 短路规则&#xff1a;在整个逻辑表…

与数学式子对应的C语言表达式是(),与数学式子3乘以x的n次方/(2x-1)对应的C语言表达式是...

满意答案 lengwei241 2013.03.25 采纳率:43% 等级:13 已帮助:11778人 18 与数学式子3乘以x的n次方/(2x-1)对应的C语言表达式是 3*x^n/(2*x-1) 3*x**n/(2*x-1) 3*pow(x,n)*(1/(2*x-1)) 3*pow(n,x)/(2*x-1) 答案是3*pow(x,n)*(1/(2*x-1)) 为什么 解答:其中pow(x,n)为C语言…