使用VC++设计程序:实现常见的三种图像插值算法:最近邻插值,双线性插值,立方卷积插值

图像放大的三种插值算法

获取源工程可访问gitee可在此工程的基础上进行学习。
该工程的其他文章:
01- 一元熵值、二维熵值
02- 图像平移变换,图像缩放、图像裁剪、图像对角线镜像以及图像的旋转
03-邻域平均平滑算法、中值滤波算法、K近邻均值滤波器
04-分段线性变换,直方图均衡化、锐化处理
05-基于拉普拉斯算子、Canny的边缘检测功能、实现Otsu分割方法

文章目录

  • 图像放大的三种插值算法
    • 实验内容
    • 一、 插值算法的原理
      • 1. 最近邻插值
      • 2. 双线性插值
      • 3. 立方卷积插值
    • 二、 实验代码与现象图
      • 1. 最近邻插值
      • 2. 双线性插值
      • 3.立方卷积插值

实验内容

B–(3)研究放大图像时使用的插值算法,使用VC++实现常见的三种图像插值算法:最近邻插值,双线性插值,立方卷积插值。通过实验验证其效果。

一、 插值算法的原理

1. 最近邻插值

最近邻插值是一种简单的插值方法,它选择离目标位置最近的已知像素值。对于二维图像上的插值,最近邻插值的公式为:

I new ( x , y ) = I old ( round ( x ) , round ( y ) ) I_{\text{new}}(x, y) = I_{\text{old}}\left(\text{round}(x), \text{round}(y)\right) Inew(x,y)=Iold(round(x),round(y))

其中:

  • $ I_{\text{new}}(x, y) $ 是目标位置的新像素值。
  • $ I_{\text{old}}(x’, y’) $是原始图像中最近邻的已知像素值,其中 $ (x’, y’) $ 由 $ (x, y) $ 四舍五入得到。

2. 双线性插值

双线性插值考虑了目标位置周围的四个最近的已知像素值,并根据其相对位置进行加权平均。对于二维图像上的插值,双线性插值的公式为:

I new ( x , y ) = ( 1 − α ) ( 1 − β ) I old ( x 1 , y 1 ) + α ( 1 − β ) I old ( x 2 , y 1 ) + ( 1 − α ) β I old ( x 1 , y 2 ) + α β I old ( x 2 , y 2 ) I_{\text{new}}(x, y) = (1 - \alpha)(1 - \beta)I_{\text{old}}(x_1, y_1) + \alpha(1 - \beta)I_{\text{old}}(x_2, y_1) + (1 - \alpha)\beta I_{\text{old}}(x_1, y_2) + \alpha \beta I_{\text{old}}(x_2, y_2) Inew(x,y)=(1α)(1β)Iold(x1,y1)+α(1β)Iold(x2,y1)+(1α)βIold(x1,y2)+αβIold(x2,y2)
其中:

  • $ I_{\text{new}}(x, y) $ 是目标位置的新像素值。
  • $ I_{\text{old}}(x_i, y_i)$是原始图像中四个最近邻的已知像素值,其中 $ (x_i, y_i) $ 是目标位置的四个相邻像素的坐标。
  • $ \alpha = x - x_1 $ 和 $ \beta = y - y_1$。

双线性插值算法涉及到目标位置周围的四个最近邻的已知像素值。这四个最近邻的像素可以通过目标位置坐标的整数部分和小数部分来确定。假设目标位置的坐标为 ((x, y)),则这四个最近邻的坐标可以表示为 ((x_1, y_1), (x_2, y_1), (x_1, y_2), (x_2, y_2)),其中:

  • x 1 = ⌊ x ⌋ x_1 = \lfloor x \rfloor x1=x x x x的整数部分;
  • x 2 = ⌈ x ⌉ x_2 = \lceil x \rceil x2=x x x x的整数部分加一;
  • y 1 = ⌊ y ⌋ y_1 = \lfloor y \rfloor y1=y y y y 的整数部分;
  • y 2 = ⌈ y ⌉ y_2 = \lceil y \rceil y2=y y y y 的整数部分加一。

这四个最近邻的坐标形成了一个矩形区域,如下图所示:

(x1, y1) ---------- (x2, y1)|                        ||                        ||                        |
(x1, y2) ---------- (x2, y2)

3. 立方卷积插值

立方卷积插值考虑了目标位置周围的八个最近的已知像素值,并使用立方卷积核进行加权平均。对于二维图像上的插值,立方卷积插值的公式较为复杂,其中涉及到立方卷积核的权重计算。

I new ( x , y ) = ∑ i = − 1 2 ∑ j = − 1 2 w ( i , j ) I old ( x + i , y + j ) I_{\text{new}}(x, y) = \sum_{i = -1}^{2} \sum_{j = -1}^{2} w(i, j)I_{\text{old}}(x + i, y + j) Inew(x,y)=i=12j=12w(i,j)Iold(x+i,y+j)

其中:

  • $ I_{\text{new}}(x, y) $ 是目标位置的新像素值。
  • $I_{\text{old}}(x + i, y + j) $ 是原始图像中八个最近邻的已知像素值,其中 $i $ 和 $j $取值为 -1, 0, 1, 2。
  • $ w(i, j) $ 是立方卷积核的权重,通常采用一些特定的卷积核形式,如 Bicubic 插值。

在立方卷积插值中,涉及到的是8个点。以下是正确的描述:

对于立方卷积插值,考虑目标位置 ( x , y ) (x, y) (x,y) 周围的8个最近邻点,其坐标可以表示为 ( x i , y j ) (x_i, y_j) (xi,yj),其中:

x i = x − 1 , 0 , 1 , 2 x_i = x - 1, 0, 1, 2 xi=x1,0,1,2
y j = y − 1 , 0 , 1 , 2 y_j = y - 1, 0, 1, 2 yj=y1,0,1,2

这样,可以得到一个包含8个点的矩阵,如下所示:

(x-1, y-1)  |  (x, y-1)  |  (x+1, y-1)  |  (x+2, y-1)
(x-1, y)    |  (x, y)    |  (x+1, y)    |  (x+2, y)
(x-1, y+1)  |  (x, y+1)  |  (x+1, y+1)  |  (x+2, y+1)
(x-1, y+2)  |  (x, y+2)  |  (x+1, y+2)  |  (x+2, y+2)

这里的坐标形成了一个4x4的矩阵,但在立方卷积插值中,只需要考虑中间的8个点。这8个点的坐标将用于计算插值权重。

二、 实验代码与现象图

1. 最近邻插值

void CImageProcessingView::OnGeoResizing()
{// 实验 图像缩放//MessageBox("请在这里添加图像缩放的代码");// 获得当前文档对象
CImageProcessingDoc* pDoc = GetDocument();// 判断图像是否已被加载if( pDoc->m_pDibInit->IsEmpty() ){MessageBox("图像未加载");return;}int width = pDoc->m_pDibInit->GetWidth();int height = pDoc->m_pDibInit->GetHeight();int bitCount = pDoc->m_pDibInit->GetBitCount();// 将 m_pDibInit 拷贝至 m_pDibTestpDoc->m_pDibTest->CloneDib(pDoc->m_pDibInit);// 考虑将图像放大两倍的情况 float nResizing = 2;// 获得新的图像高度int newWidth = width*nResizing;int newHeight = height*nResizing;pDoc->m_pDibTest->SetWidthHeight(newWidth, newHeight);//*****************************图像的插值1最近邻插值算法************//int i=0;int j=0;float src_x, src_y;RGBQUAD Quad1;for(i=0;i<newWidth;i++)for(j=0;j<newHeight;j++){src_x = (i / nResizing) + 0.5; //四舍五入src_y = (j / nResizing) + 0.5;Quad1=pDoc->m_pDibInit->GetPixelColor(src_x,src_y);pDoc->m_pDibTest->SetPixelColor(i,j,&Quad1);}// 交换 m_pDibInit 与 m_pDibTest 指针CDib* pTmp = pDoc->m_pDibInit;pDoc->m_pDibInit = pDoc->m_pDibTest;pDoc->m_pDibTest = pTmp; // 设置脏标记pDoc->SetModifiedFlag(TRUE);// 更新视图pDoc->UpdateAllViews(NULL);
}

实验现象.
图像放大2倍
在这里插入图片描述

2. 双线性插值

 int i=0;int j=0;for(i=0;i<newWidth;i++)for(j=0;j<newHeight;j++){int x=i/nResizing, y = j / nResizing;  //定位,找周围四个点float u = i / nResizing,v = j / nResizing; //注意这个类型u =u - x;          //所占权重系数v =v - y;int gray0 , gray1 , gray2 , gray3 , GRAY ;gray0 = pDoc->m_pDibInit->GetPixelGray(x, y);//边界处理 非补零if (x + 1 < 256)gray1 = pDoc->m_pDibInit->GetPixelGray(x+1, y);elsegray1 = pDoc->m_pDibInit->GetPixelGray(x, y);if (y + 1 < 256)gray2 = pDoc->m_pDibInit->GetPixelGray(x, y + 1);elsegray2 = pDoc->m_pDibInit->GetPixelGray(x, y);if (x + 1 < 256 && y + 1 < 256)gray3 = pDoc->m_pDibInit->GetPixelGray(x + 1, y + 1);elsegray3 = pDoc->m_pDibInit->GetPixelGray(x, y);GRAY = (1 - u) * (1 - v) * gray0 + (1 - u) * v * gray2 + u * (1 - v) * gray1 + u * v * gray3;pDoc->m_pDibTest->SetPixelGray(i, j, GRAY);}// 交换 m_pDibInit 与 m_pDibTest 指针CDib* pTmp = pDoc->m_pDibInit;pDoc->m_pDibInit = pDoc->m_pDibTest;pDoc->m_pDibTest = pTmp;

实验效果图.

在这里插入图片描述

3.立方卷积插值

int a = -0.5;   //系数for(int i=0;i<newWidth;i++)for (int j = 0; j < newHeight; j++){int x[4] = { 0 }, y[4] = { 0 };x[1] = i / nResizing, y[1] = j / nResizing;  //找点,(1,1)位置x[0] = x[1] - 1; y[0] = y[1] - 1;x[2] = x[1] + 1; y[2] = y[1] + 1;x[3] = x[1] + 2; y[3] = y[1] + 2;float u = (i) / nResizing, v = (j) / nResizing;u =u - x[1];   //所占权重系数(大于0小于1)v =v - y[1];int gray[4][4] = { 0 };float w_x[4] = { 0 }, w_y[4] = { 0 };w_x[0] = 1 + u; w_x[1] = u; w_x[2] = 1 - u; w_x[3] = 2 - u;w_y[0] = 1 + v; w_y[1] = v; w_y[2] = 1 - v; w_y[3] = 2 - v;float W_x[4] = { 0 }, W_y[4] = { 0 };for (int k = 0; k < 4; k++)    //计算x和y的权重{if (w_x[k] <= 1 && w_x[k] >= -1)W_x[k] = (a + 2) * pow(w_x[k], 3) - (a + 3) * pow(w_x[k], 2) + 1;else if (w_x[k] > 1 && w_x[k] < 2) W_x[k] = a * pow(w_x[k], 3) - 5 * a * pow(w_x[k], 2) + 8 * a * w_x[k] - 4 * a;elseW_x[k] = 0;if (w_y[k] <= 1 && w_y[k] >= -1)W_y[k] = (a + 2) * pow(w_y[k], 3) - (a + 3) * pow(w_y[k], 2) + 1;else if (w_y[k] > 1 && w_y[k] < 2)W_y[k] = a * pow(w_y[k], 3) - 5 * a * pow(w_y[k], 2) + 8 * a * w_y[k] - 4 * a;elseW_y[k] = 0;}for(int k=0;k<4;k++)for (int m = 0; m < 4; m++){if (x[k] > 0 && x[k]<height && y[m] > 0 && y[m] < width) //判断边界gray[k][m] = pDoc->m_pDibInit->GetPixelGray(x[k], y[m]);elsegray[k][m] = 0;}int Pix_gray = 0;  //最终计算得到的灰度值for(int k=0;k<4;k++)for (int m = 0; m < 4; m++){Pix_gray += gray[k][m] * W_x[k] * W_y[m];}pDoc->m_pDibTest->SetPixelGray(i, j, Pix_gray);}

实验效果图.
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/171157.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电子学会C/C++编程等级考试2022年09月(二级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:统计误差范围内的数 统计一个整数序列中与指定数字m误差范围小于等于X的数的个数。 时间限制:5000 内存限制:65536输入 输入包含三行: 第一行为N,表示整数序列的长度(N <= 100); 第二行为N个整数,整数之间以一个空格分…

Deepin使用记录-deepin系统开启SSH服务

1、检查安装的deepin系统是否已经开启SSH功能。 $ ps -e | grep ssh $ ps -e | grep ssh 查看是否启动ssh 2、安装openssh-server服务 sudo apt-get install openssh-server 如果出现以上提示&#xff0c;就表示你已经安装了ssh服务&#xff0c;只是还没有启动。 3、安装完…

快速幂算法详解(C++实现)

文章目录 1. 什么是快速幂2. 暴力求解代码实现缺陷分析 3. 优化一&#xff1a;取模运算的性质4. 优化二&#xff1a;快速幂算法的核心思想5. 终极优化&#xff1a;位运算优化6. 源码 这篇文章我们来一起学习一个算法——快速幂算法。 1. 什么是快速幂 顾名思义&#xff0c;快速…

leetCode 1080.根到叶路径上的不足节点 + 递归

给你二叉树的根节点 root 和一个整数 limit &#xff0c;请你同时删除树中所有 不足节点 &#xff0c;并返回最终二叉树的根节点。假如通过节点 node 的每种可能的 “根-叶” 路径上值的总和全都小于给定的 limit&#xff0c;则该节点被称之为 不足节点 &#xff0c;需要被删除…

C语言-内存函数详解

文章目录 1. memcpy使用和模拟实现2. memmove使用和模拟实现3. memset函数的使用4. memcmp函数的使用 1. memcpy使用和模拟实现 返回类型和参数&#xff1a; void * memcpy ( void * destination, const void * source, size_t num );1.函数memcpy从source的位置开始向后复制…

R语言实现Lasso回归

一、Lasso回归 Lasso 回归&#xff08;Least Absolute Shrinkage and Selection Operator Regression&#xff09;是一种用于线性回归和特征选择的统计方法。它在回归问题中加入了L1正则化项&#xff0c;有助于解决多重共线性&#xff08;多个特征高度相关&#xff09;和特征选…

设备树是什么?

设备树&#xff1a; 设备树DTS(Device Tree Source) 描述设备信息的独立的文件。 为什么要引入设备树&#xff1f; 随着芯片的发展&#xff0c;Linux内核中就包含着越来越多这些描述设备的代码&#xff0c;导致Linux内核代码会很臃肿。因此引入了设备树文件&#xff0c;从…

基于 GPS 定位信息的 Pure-Pursuit 轨迹跟踪实车测试(1)

基于 GPS 定位信息的 Pure-Pursuit 轨迹跟踪实车测试&#xff08;1&#xff09; 进行了多组实验&#xff0c;包括顺逆时针转向&#xff0c;直线圆弧轨迹行驶&#xff0c;以及Pure-Pursuit 轨迹跟踪测试 代码修改 需要修改的代码并不多&#xff0c;主要对 gps_sensor 功能包和…

Java中的泛型是什么?如何使用泛型类和泛型方法?

Java 中的泛型是一种编程机制&#xff0c;允许你编写可以与多种数据类型一起工作的代码&#xff0c;同时提供编译时类型检查以确保类型的安全性。泛型的主要目的是提高代码的可重用性、类型安全性和程序的整体性能。 泛型类&#xff08;Generic Class&#xff09;: 在泛型类中…

【教3妹学编程-算法题】统计子串中的唯一字符

3妹&#xff1a;“太阳当空照&#xff0c;花儿对我笑&#xff0c;小鸟说早早早&#xff0c;你为什么背上炸药包” 2哥 :3妹&#xff0c;什么事呀这么开发。 3妹&#xff1a;2哥你看今天的天气多好啊&#xff0c;阳光明媚、万里无云、秋高气爽&#xff0c;适合秋游。 2哥&#x…

关于python中的nonlocal关键字

如果在函数的子函数中需要调用外部变量&#xff0c;一般会看见一个nonlocal声明&#xff0c;类似下面这种&#xff1a; def outer_function():x 10def inner_function():nonlocal xx 1print(x)inner_function()outer_function()在这个例子中&#xff0c;inner_function 引用…

【DevOps】基于 KubeSphere 的 Kubernetes 生产实践之旅(万字长文)

基于 KubeSphere 的 Kubernetes 生产实践 1.KubeSphere 简介1.1 全栈的 Kubernetes 容器云 PaaS 解决方案1.2 选型理由&#xff08;从运维的角度考虑&#xff09; 2.部署架构图3.节点规划3.1 软件版本3.2 规划说明3.2.1 K8s 集群规划3.2.2 存储集群3.2.3 中间件集群3.2.4 网络规…

SpringBoot——LiteFlow引擎框架

优质博文&#xff1a;IT-BLOG-CN 一、LiteFlow 简介 LiteFlow是一个轻量且强大的国产规则引擎框架&#xff0c;可用于复杂的组件化业务的编排领域。帮助系统变得更加丝滑且灵活。利用LiteFlow&#xff0c;你可以将瀑布流式的代码&#xff0c;转变成以组件为核心概念的代码结构…

计算机组成原理-Cache的基本概念和原理

文章目录 存储系统存在的问题Cache的工作原理局部性原理性能分析例题界定何为局部部分问题总结 存储系统存在的问题 增加Cache层来缓和CPU和主存的工作速度矛盾 Cache的工作原理 启动某个程序后&#xff0c;将程序的代码从辅存中取出放入内存中&#xff0c;再从内存中将代码…

机器人开发的选择

喷涂机器人 码垛机器人 纸箱码垛机器人 焊接机器人 跳舞机器人 管道清理机器人 工地巡检机器人 点餐机器人 化工巡检机器人 装箱机器人 安防巡检机器人 迎宾机器人好像有点像软银那个 污水管道检测机器人 大酒店用扫地机器人 家用扫地机器人 工厂用&#xff08;…

S25FL系列FLASH读写的FPGA实现

文章目录 实现思路具体实现子模块实现top模块 测试Something 实现思路 建议读者先对 S25FL-S 系列 FLASH 进行了解&#xff0c;我之前的博文中有详细介绍。 笔者的芯片具体型号为 S25FL256SAGNFI00&#xff0c;存储容量 256Mb&#xff0c;增强高性能 EHPLC&#xff0c;4KB 与 6…

Leetcode199. 二叉树的右视图

Every day a Leetcode 题目来源&#xff1a;199. 二叉树的右视图 解法1&#xff1a;层序遍历 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 按层序遍历&#xff0c;将每层的…

如何判断一个题目用“贪心/动态规划“还是用“BFS/DFS”方法解决

1 总结 1.1 贪心、动态规划和BFS/DFS题解的关系 一般能使用贪心、动态规划解决一个问题时&#xff0c;使用BFS&#xff0c;DFS也能解决这个题&#xff0c;但是反之不能成立。 1.2 2 贪心 -> BFS/DFS 2.1 跳跃游戏1和3的异同 这两道题&#xff0c;“跳跃游戏”&#xf…

html实现各种瀑布流(附源码)

文章目录 1.设计来源1.1 动态响应瀑布流1.2 分页瀑布流1.3 响应瀑布流 2.效果和源码2.1 动态效果2.2 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/134613121 html实现各种瀑布流(附源码)&#xff0c;…

100元预算,轻松涨粉1000!腾讯运营面试秘籍大揭秘!

大家好啊&#xff01;小米在这里&#xff5e; 很高兴又有机会和大家见面啦&#xff01;最近小米参加了一场腾讯的运营面试&#xff0c;遇到了一个超有趣的问题&#xff1a;如果让你运营一个公众号&#xff0c;近期需要增加1000个关注&#xff0c;预算100元&#xff0c;怎么完成…