本学期修读“数学实验”相关课程,课程设计以“双线性插值法实现图像缩放”为研究方向,写篇博文记录一下自己的心路历程–
前言
matlab以强大的数据处理和科学计算能力,在信号,图像处理等等多个领域获得广泛应用。因此,了解和掌握matlab编程方法,以及学习如何利用matlab解决科研中的实际问题是非常重要的。本博文以“双线性插值法实现图像缩放”课程设计为依托,介绍双线性插值法以及如何利用matlab实现双线性插值法以解决图像缩放的问题。
一、图像基础知识
所谓的图像,其实是由一个个像素点组成的,相信大家在观察照片时,都会发现如果将图像放大至一定倍数,图像清晰度会下降,甚至可以看到其中一个一个的小方块,这实际上就是我们的像素点。由于图像是由若干像素点组成的,因此,图像放大和缩小的本质实际上是在增加或者减少像素点的个数,因此我们只需要为缩放后图像对应位置上填充相应的像素值并进行图像显示后即可以得到缩放后的图像。 至于如何为缩放后图像的相应位置填充上相应的像素值,这就是“双线性插值法”发挥的作用。
本文主要针对于日常生活中常见的两种图像进行处理---灰度图像和彩色图像:
(1)灰度图像是每个像素只有灰度值的图像,仅具有一个通道。这类图像通常显示为从最暗黑色到最亮的白色的灰度,灰度图像每个像素的灰度值是一个由黑到白的区间。
(2)彩色图像是指图像中的每个像素都分成R、G、B三个基色分量,每个基色分量直接决定其基色的强度,这样产生的色彩称为真彩色,彩色图像与灰度图像不同,具有3个通道。
二、双线性插值法
1.算法简介
双线性插值法: 双线性插值法用于求解缩放后图像中各点处的像素值,是为解决像素求解问题而建立数学模型。双线性插值法主要针对于“虚点”处的像素求解,所谓的“虚点”指的是缩扩后的图像像素点对应于原图像像素点的坐标值并非整数, 但由于原图像像素点坐标值均为整数,这时,不存在“现成”的对应关系,这时,采用“双线性插值法”借助于“虚点”周围的四个整数点计算该“虚点”处的像素值。双线性插值法模型本质可以简化为三个相似三角形结合求解像素值。通过原图像与处理图像的缩扩比例,可以求得新图像B在(i,j)处对应原图像的点为(x,y)(其中x = 1*h/scale_h,y = j*w/scale_w) 但是这两个值可能为浮点数,而像素中的位置是整数,所以这个点在在原图像中对应的可能为“虚”点,所以,我们需要借助该“虚”点周围四个点进行双线性插值求解新图像像素值。
数学模型建立:
数学模型说明:
数学模型建立中的z1,z2和z分别对应于数学模型说明中三个相似三角形求解过程,以具体示例说明:
所谓双向插值法,就是在两个方向上进行插值求解虚点处的像素值,以(1.2,1.6)点为例,首先便是在x = 1上进行插值,利用相似三角形进行像素值求解:(1.6-1)/1 = 像素值1 /(11-7)可以计算出x = 1方向上的像素值。另外在x = 2方向上进行插值求解虚点处的像素值,利用相似三角形进行像素值求解:(1.6-1)/1 = 像素值2/(14-10)可以计算出x = 2方向上的像素值。最终在x方向上进行第三个相似三角形求解像素值:(1.2-1)/1 = 像素值3/(像素值2 – 像素值1)
本质说明---------已知四个相邻整数坐标点的函数值,如何通过数学建模的方式计算四个点所围成正方形中任意一点的函数值。
2.算法实现
代码如下(示例):
% 灰度图像处理
function test
scale('image_1.png',[512,768])
%'image_1'---目标图像 [512,768]---缩放目标大小
function output_img = scale(input_img,scale_size)
A = imread(input_img); % 图像读取--imread
img = A(:,:,3); % imread命令读取得三个矩阵,灰度图像,三个矩阵相同
[h,w] = size(img); % 获取行和列,即原图像的大小
% h = 256 w = 384
scale_h = scale_size(1); % 根据输入获取缩放后的图像的大小,即缩扩后图像的高度和宽度
scale_w = scale_size(2);
output_img = zeros(scale_h,scale_w); % 初始化全零矩阵,用于存储缩扩后图像像素值
for i = 1:scale_h
for j = 1:scale_w % 遍历处理后图像每一个像素点,计算像素值
x = i.*h / scale_h; % x:高度
y = j.*w / scale_w; % y:宽度
u = x - floor(x);
v = y - floor(y); % 获取小数部分,用于相似计算
if x < 1
x = 1;
end % 边缘处理
if y < 1
y = 1;
end % 边缘处理
output_img(i,j) = v.*(u.*img(ceil(x),ceil(y)) + (1 - u).*img(floor(x),ceil(y))) + ...
(1 - v).*(u.*(img(ceil(x),floor(y))) + (1-u).*img(floor(x),floor(y))); % 特定点像素计算公式
end
end
% imwrite(uint8(output_img),'../output_img.png');
imshow(input_img)
title('原灰度图像')
figure,imshow(uint8(output_img)) % 显示处理后的图像 unit8保证像素值取值在0-255(2^8)之间
title('插值法压缩图像')
figure,imshow(imresize(img,2)) %matlab自带图像缩放函数,与插值法进行比较
title('函数法压缩图像')
function test
scale('image_3.jpg',[2160,3840])
function output_img = scale(input_img, scale_size)
img = imread(input_img);
[h,w] = size(img(:,:,1))
scale_h = scale_size(1);
scale_w = scale_size(2);
output_img = zeros(scale_h, scale_w,3); %初始化三个全零矩阵,分别用于RGB三原色存储
for m = 1:3 % 循环三次,针对于RGB三个通道
for i = 1 : scale_h %缩放后的图像的(i,j)位置对应原图的(x,y)
for j = 1 : scale_w
x = i * h / scale_h;
y = j * w / scale_w;
u = x - floor(x);
v = y - floor(y); %取小数部分,对应于相似比例的计算
if x < 1 %边界处理
x = 1;
end
if y < 1
y = 1;
end
%用原图的四个真实像素点来双线性插值获得“虚”像素的像素值
output_img(i, j,m) = img(floor(x), floor(y),m) * (1-u) * (1-v) + ...
img(floor(x), ceil(y),m) * (1-u) * v + ...
img(ceil(x), floor(y),m) * u * (1-v) + ...
img(ceil(x), ceil(y),m) * u * v;
end
end
end
imshow(input_img); %显示原图
title('原彩色图像')
figure,imshow(uint8(output_img)) %显示处理后的图像
title('插值法压缩图像')
figure,imshow(imresize(img,2))
title('函数法压缩图像')
总结
“双线性插值法”是图像缩扩领域基础算法之一,算法设计依靠数学建模思想,简单易得,使用几十行代码即可实现“双线性插值法”算法,达到图像缩扩较好的实验效果。 个人认为“双线性插值法”的重要意义在于提供一种图像缩扩的算法思想,即增加或减少像素点的数量进而实现图像的缩扩,至于采用何种方式改变像素点数量,以及采用何种方式实现原图像和新图像像素点的映射关系,每个人或许都有自己独到的想法。本博文依托于自己的课程设计,如有偏驳,欢迎一起讨论,共同进步!!!
项目完整代码及附件已上传至GitHub,GitHub链接:https://github.com/booue/picture-processing