《数字图像处理基础》学习07-图像几何变换之最近邻插值法放大图像

目录

一,概念

二,题目及matlab实现

1,解题思路

2,matlab实现 

1)matlab思路

2)完整代码

三,放大图像及matlab实现 


一,概念

通过上一篇,我已经学习了使用最邻近插值法来缩小图像

《数字图像处理基础》学习06-图像几何变换之最邻近插值法缩小图像-CSDN博客

依旧需要使用到如下公式(因为在上一篇文章已经学习过,所以这里不赘诉):

g(i,j)=f(i\times \Delta i,j \times \Delta j)

和使用最邻近插值法缩小图像不同。如果要使用最邻近插值法放大图像,则需要将原始图像的每行 i 和每列 j 都乘上对应的放大倍数  k ,得到原始图像中像素值的像素点(即像素值的坐标)的最大分布。

例如,有一个原始图像矩阵 f 尺寸大小为 M\times N,将其放大 k1 \times k2 倍 ,可得到尺寸大小为 k1 \cdot M\times k2 \cdot N 的放大图像矩阵 g

接着将原始图像矩阵的第一个元素的坐标(i,j),分别乘上对应的放大倍数(如果是非等比例放大则k有两个不同的取值:k1 和 k2 ),此时原始图像第 1 行第 1 列的像素值会跑到放大图像的第

1 \times k1 行第1 \times k2 列,并且放大图像从  1 \rightarrow 1 \times k1 行 及1 \rightarrow 1 \times k2 列之间的像素值都用原始图像的第 1 行第 1 列的像素值来填充。如果放大倍数是小数,则计算后按照四舍五入法取值。接下来可以通过题目来加深使用最邻近插值法放大图像的具体过程。

二,题目及matlab实现

下面是一个简单的例子。给出一个原始图像矩阵 f  大小为 3\times 3 

f=\begin{bmatrix} 1 & 4&7 \\ 2& 5 & 8\\ 3& 6 &9 \end{bmatrix}

将其放大:

  1. 高(行)放大的倍数为 k1=1.2
  2. 宽(列)的放大倍数为 k2=2.5 

求对其放大后的图像矩阵 g

% 可以试着先自己做一做,如果解出来的g如下:

g=\begin{bmatrix} 1 & 1 & 1 & 4 & 4 & 7 & 7 & 7 \\ 2 & 2 & 2 & 5 & 5& 8 & 8 & 8 \\ 3 & 3 & 3 & 6 & 6 & 9 & 9 & 9 \\ 3 & 3 & 3 & 6 & 6 & 9 & 9 & 9 \\ \end{bmatrix}

则思路正确,直接用自己的思路编写matlab程序去处理读取的图像,下面的解题思路可以选择跳过。

1,解题思路

从之前的概念中就已经可以用手算出g。

例如:

  1. 首先根据放大原始图像 f 的行列倍数创建一个放大后的图像矩阵 g 

  2. 原始图像 f 第 1 行第 1 列的像素值会跑到放大图像 g 的第 1 行第1 \times k2=1 \times 2.5 \approx3 列,并且放大图像 g 从  1 \rightarrow 1 行 及1 \rightarrow3 列之间的像素值都用原始图像 f 的第 1 行第 1 列的像素值来填充,如下👇

  3. 原始图像 f 第 1 行第 2 列的像素值会跑到放大图像 g 的第 1 行第5 列,并且放大图像 g 从  1 \rightarrow 1 行 及4 \rightarrow5 列之间的像素值都用原始图像的第 1 行第 2 列的像素值来填充,如下👇

    可以看到,填充 g 时的起始位置跟上一次的填充的列结束位置有关,例如,上一次的填充在 j=3 结束,那么这一次的填充从 j+1=4 开始,一直填充到 j=5 为止。原始图像 f 第 1 行第 3 列的像素值操作一样。

  4. 原始图像 f 第 2 行第 1 列的像素值会跑到放大图像 g 的第 2 行第3 列,并且放大图像 g 从  2 \rightarrow 2 行 及1 \rightarrow3 列之间的像素值都用原始图像的第 2 行第 1 列的像素值来填充,如下👇

    可以看到,填充 g 时的起始位置跟上一次的填充的行结束位置有关,例如,上一次的填充在 i=1 结束,那么这一次的填充从 i+1=2 开始,一直填充到 i=2 \times 1.2=2.4 \approx 2  为止。

  5. 后面的操作类似,这里不赘诉,最后得到的放大矩阵g如下👇

2,matlab实现 

1)matlab思路

在通过解题思路中,可以看到在填充过程中,不变的是原始图像矩阵中的每一个像素放大后的对应像素点(像素的坐标,i,j),因此, 读取图像形成矩阵 f 和产生全零的放大矩阵 g 之后,可以先将原始图像矩阵的每一行每一列放大后在放大图像矩阵中的位置分别用数组存储起来:

  • 数组 ia ,存储原始图像矩阵的每一行放大后在放大图像矩阵中的最大位置。
  • 数组 ja,存储原始图像矩阵的每一列放大后在放大图像矩阵中的最大位置。

虽然matlab在声明一维数组时可以不用声明一维数组的类型及指定一维数组的大小,但至少得有一个数组元素。例如,ia=[1];  % 数组ia中有一个元素 1

 于是,需要在matlab中写下如下语句,创建数组ia和数组ja:

ia=[1];  %之所以给定元素1,是因为在matlab中索引是从1开始,不管是遍历原始图像矩阵的行列,还是填充放大图像矩阵的行列,它们的第一个元素的行都是从1开始,列也是从1开始,即第一个元素的坐标为(1,1)
ja=[1];
for i=1:h  % 原始图像的高(行数)ia(end+1)=round(i*k1)+1;  % 创建存储原始图像矩阵的每一行放大后在放大图像矩阵中的最大位置的数组
% ia(end+1)可以在数组ia的已有元素末尾添加新的数组元素
end
for j=1:w % 原始图像的宽(列数)ja(end+1)=round(j*k2)+1;  % 创建存储原始图像矩阵的每一列放大后在放大图像矩阵中的最大位置的数组
end

 上述创建数组的代码也可以简化成如下形式(如果后面嵌套多的话就需要用到简化)👇:

ia = round((0:h) * k1) + 1;  
% 之所以要加1,是因为原始图像矩阵在当前行或列在放大时,得到的就是在放大图像矩阵中的最大位置
% 而下一个填充的行或列的填充位置需要上一个位置加1,为了方便起见,都将结果加1,之后遍历的时候再进行相应的处理。
ja = round((0:w) * k2) + 1;

接下来就开始遍历原始图像矩阵,为了后期让这个代码也可以应用到图像处理中,因此,还需要加上用来遍历像素值的颜色通道变量 c(在获取原始图像矩阵 f 时,获取到该图像的颜色通道数dim,之后在创建放大图像矩阵 g 时,也需要传入颜色通道数 dim)。像给出的题目中的图像矩阵 f 很简单,所以也不包含颜色,不是彩色图像,因此,是灰度图像,它的颜色通道数 dim=1

我通过最邻近插值法的相关概念和解题思路,可以知道,放大图像被填充的像素值与上一次的填充有关,而相关的坐标已经用数组 ia 和 ja 存储:

  1. 例如:原始图像 f 只有两行,所产生的数组ia只有3个元素:1;1*k1+1;2*k1+1。数组ja也只有三个元素:1;1*k2+1;2*k2+1。
  2. 如果想要遍历整个数组ia,只需要循环两次就行,因为通过观察,可以发现遍历数组ia 和 ja 的循环次数分别与原始图像矩阵的行数和列数一样。
  3. 我一般喜欢按照将变量名命名成与之相关的其它变量。例如,如果想要遍历原始图像 f 的行 h ,我就会用 fi 表示原始图像 f 的每一行。fj 表示原始图像 f 的每一列。
  4. 在填充的过程中,放大图像 g 的像素值的行 gi 和列 gj 都会变化:起始位置对应数组的当前元素,结束位置为对应数组的下一个元素的值减一。
    【可以自己选择带入个别的值来验证】

根据上述写出的代码如下👇

for c=1:dimfor fi=1:hfor fj=1:wfor gi=ia(fi):ia(fi+1)-1for gj=ja(fj):ja(fj+1)-1g(gi,gj,c)=f(i,j,c);endendendend
end

由于嵌套过多,会导致运算出现问题,因此,可以将最里面的两个循环语句简化,如下:

for c = 1:dimfor fi = 1:hfor fj = 1:wg(ia(fi):(ia(fi+1)-1), ja(fj):(ja(fj+1)-1), c) = f(fi,fj,c);endend
end

2)完整代码

clear all; clear; clc;% 清空工作空间
f = [1, 4, 7; 2, 5, 8; 3, 6, 9];   
[h,w,dim] = size(f);
k1 = 1.2;  
k2 = 2.5;
nh = round(k1 * h);
nw = round(k2 * w);  
g = zeros(nh, nw, dim, 'uint8'); 
ia = round((0:h) * k1) + 1;
ja = round((0:w) * k2) + 1;
for c = 1:dimfor fi = 1:hfor fj = 1:wg(ia(fi):(ia(fi+1)-1), ja(fj):(ja(fj+1)-1), c) = f(fi,fj,c);endend
end
% 显示结果
disp('输入矩阵 f:');
disp(f); 
disp('输出矩阵 g:');
disp(g);

运行后的结果和之前通过做题得到的结果一样:

三,放大图像及matlab实现 

clear all; clear; clc; % 清空工作空间
f = imread('01.jpg');  
[h,w,dim] = size(f);
k1 = 1.2;  
k2 = 2.5;
nh = round(k1 * h);
nw = round(k2 * w);  
g = zeros(nh, nw, dim, 'uint8'); 
ia = round((0:h) * k1) + 1;
ja = round((0:w) * k2) + 1;for c = 1:dimfor fi = 1:hfor fj = 1:wfv = f(fi, fj, c);g(ia(fi):(ia(fi+1)-1), ja(fj):(ja(fj+1)-1), c) = fv;endend
end
disp('图像处理完成。');
figure;
subplot(121);
imshow(f);
title(['分辨率为:', num2str(size(f, 1)), '×', num2str(size(f, 2)), '的原图像']);
subplot(122);
imshow(g);
title(['分辨率为:', num2str(size(g, 1)), '×', num2str(size(g, 2)), '的放大图像']);
imwrite(g, 'D:\myMatlab\img\01near_increase.jpg');

如果想要等比例放大图像,可以将放大倍数k1和k2设置一样的数值。如下就是等比例放大6倍的图像👇 

一般来说,很少用最邻近插值法来放大图像,基本使用的时双线性插值法来放大图像,之所以我要写这篇文章,主要是因为刚刚好学了,想着雁过留痕,就将自己的学习记录下来,往后还可以再看看。

如果有兴趣的话,可以关注专栏,之后会持续更新有关数字图像处理相关的内容及知识点。

如下就是双线性插值法的核心图:通过邻近四点,求得缩放图像的 像素值 g(i,j) 👇

如果对文章的内容有问题或者是有更好的建议请在评论区留言或者是私信我,回复时间不超过一天。  

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

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

相关文章

计网-子网划分

基于本视频观看做的笔记,帮助自己理解 子网掩码:用于识别IP地址中的网络号和主机号的位数 表示方法 第一种.32位二进制数字,在子网掩码中,网络号用”1“表示,主机号用”0“表示 e.g.:IP地址1.1.1.1的子网掩码是255…

【Solidity】入门指南:智能合约开发基础

🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 ​💫个人格言: "如无必要,勿增实体" 文章目录 Solidity入门指南:智能合约开发基础引言1. 开发环境搭建1.1 Remix I…

如何高效地架构一个Java项目

引言 Java是企业级应用开发的主流语言之一,而我们作为使用Java语言的程序员,职称有初级、中级、高级、资深、经理、架构,但我们往往只是慢慢通过经验的积累迭代了自己的等级,如果没有保持学习的习惯,大多数程序员会停留…

HTTP 探秘之旅:从入门到未来

文章目录 导言:目录:第一篇:HTTP,互联网的“快递员”第二篇:从点开网页到看到内容,HTTP 究竟做了什么?第三篇:HTTP 的烦恼与进化史第四篇:HTTP 的铠甲——HTTPS 的故事第…

前端处理sql参数替换问题,即使有重复参数,也可以按顺序替换

我们可以创建一个通用的模板函数,能够处理任意SQL语句中的占位符替换。这个函数将接受两个参数: sqlTemplate:包含占位符的SQL模板字符串。params:一个对象数组,每个对象包含name和value,用于替换SQL模板中的占位符。通用模板函数 function replaceSqlPlaceholders(sqlT…

Fabric.js 中文文档

Fabric.js 中文文档 基于canvas画布的实用类Fabric.js的使用 4、Fabric.js 常用的方法&事件 Fabric.js 画布 defaultCursor 属性(1) 官网文档地址:http://fabricjs.com/docs/github 地址:https://github.com/fabricjs/fabric.js Demo地址&#x…

c++:thread(线程)

1.基本使用 1.1创建线程 join()函数用于&#xff1a;主程序等待子线程执行完毕之后再继续 #include <iostream> #include <thread>void printHello() {std::cout << "hello world" << std::endl; }int main() {// 1.创建线程std::thread …

第六届金盾信安杯-SSRF

操作内容&#xff1a; 进入环境 可以查询网站信息 查询环境url https://114.55.67.167:52263/flag.php 返回 flag 就在这 https://114.55.67.167:52263/flag.php 把这个转换成短连接&#xff0c;然后再提交 得出 flag

Spark优化--开发调优、资源调优、数据倾斜调优和shuffle调优等

针对Spark优化&#xff0c;我们可以从多个角度进行&#xff0c;包括开发调优、资源调优、数据倾斜调优和shuffle调优等。以下是一些具体的优化方法&#xff1a; 1. 开发调优 避免创建重复的RDD&#xff1a;对于同一份数据&#xff0c;只应该创建一个RDD&#xff0c;避免创建多…

PHP和GD库如何调整图片尺寸

PHP和GD库可以通过一系列函数调整图片的尺寸。以下是一个详细的步骤说明&#xff1a; 一、准备工作 检查GD库是否安装&#xff1a; 使用命令php -i | grep -i gd来检查GD库是否已经安装。如果返回类似于“GD Support > enabled”的内容&#xff0c;则表示安装成功。如果没有…

递归算法讲解(c基础)

递归的定义 递归是指在函数的定义中使用函数自身的方法。它是一种解决问题的策略&#xff0c;将一个大型复杂的问题逐步分解为规模更小的、与原问题相似的子问题来解决。当子问题的规模足够小&#xff0c;达到一个可以直接求解的基本情况&#xff08;也称为终止条件&#xff09…

有一个已经排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。-多语言

目录 C 语言实现 Python 实现 Java 实现 Js 实现 题目&#xff1a;有一个已经排好序的数组。现输入一个数&#xff0c;要求按原来的规律将它插入数组中。 程序分析&#xff1a;首先判断此数是否大于最后一个数,然后再考虑插入中间的数的情况,插入后此元素之后的数,依次后移…

SpringMVC(2)

前言 这一节我们终结springmvc 1. SSM整合配置 先导入坐标 先创建包 配置类 然后开始创建jdbc的config和mybatis的config&#xff0c;还有properties SpringConfig&#xff1a; jdbc.properties&#xff1a; JdbcConfig: MybatisConfig: 下面开始spring整合mvc&#…

颜色分类

颜色分类 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums &#xff0c;原地 对它们进行排序&#xff0c;使得相同颜色的元素相邻&#xff0c;并按照红色、白色、蓝色顺序排列。 我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 必须在不使用库内置的 sort 函数…

零基础Python学习

1.环境搭建 1.1 安装运行环境python3.13 Welcome to Python.org 1.2 安装集成开发环境PyCharm PyCharm: the Python IDE for data science and web development 1.3 创建项目 && 设置字体 2.基础语法 2.1 常量与表达式 在python中整数除整数不会优化&#xff0c;所…

vue3项目创建方式记录

目录 创建vue3常用的方式有三种&#xff1a;一.使用vue cli创建二.使用vite创建三.使用vue3官方推荐创建方式&#xff08;create-vue&#xff09; 创建vue3常用的方式有三种&#xff1a; 一.使用vue cli创建 vue create 项目名二.使用vite创建 vite是下一代前端开发与构建工…

【无标题】JAVA策略模式代码例子

在Java中&#xff0c;您可以使用面向对象编程中的继承和多态性来实现您的需求。首先&#xff0c;我们定义一个Good类&#xff0c;该类包含满减策略和打折策略。然后&#xff0c;我们可以让Shoe类和Cloth类继承自Good类。为了实现不同的折扣或满减策略&#xff0c;可以考虑使用策…

cocos creator 触摸事件官方案例

cocos creator 触摸事件官方案例 1、官方示例&#xff1b; 2、对官方示例的总结&#xff1a; &#xff08;1&#xff09;介绍了鼠标事件和触摸事件的类型&#xff0c;这里主要关注的是在移动端和PC端都可以触发的触摸事件。 &#xff08;2&#xff09;节点事件的派发&#…

用MATLAB符号工具建立机器人的动力学模型

目录 介绍代码功能演示拉格朗日方法回顾求解符号表达式数值求解 介绍 开发机器人过程中经常需要用牛顿-拉格朗日法建立机器人的动力学模型&#xff0c;表示为二阶微分方程组。本文以一个二杆系统为例&#xff0c;介绍如何用MATLAB符号工具得到微分方程表达式&#xff0c;只需要…

Mongodb入门到放弃

Mongodb分片概括 分片在多台服务器上分布数据的方法&#xff0c; Mongodb使用分片来支持具有非常大的数据集和高吞吐量的操作的部署 具有大数据集和高吞吐量应用程序的数据库系统&#xff0c;可以挑战单台服务器的容量。 例如&#xff0c;高查询率可以耗尽服务器的cpu容量&…