图像在旋转或者缩放操作时候会需要插值操作,插值操作就是在像素间插入未知的像素值。
常见的插值算法有最近邻插值算法,双线性插值算法,三次卷积等
最近邻插值算法
这是最简单的一种插值算法,根据目标图像(插值后的图像大小)与源图像大小的比值来寻找目标图像的像素位置对应于源图像像素的位置。
比如说源图像是3*3的大小,插值后的目标图像数4*4的大小
目标图像G(i,j)代表第i行j列的像素值,我们现在要从源图像中找到对应的像素来填补目标G(i,j)的值。
设源图像的大小为srcx*srcy,目标图像的大小为desx*desy,缩放比为factor
那么目标图像G(i,j)处对应的源图像位置为F(i*(desx/factor),j*(desy/factor))
其中desx/factor可以做向下取整运算,因为坐标位置都是整数
Matlab简单实现
function imt=change_pixels(ima,factor)
[xs,ys] = size(ima);
if factor<0 % shrink the image
fa = abs(factor)
%imt = zeros((xs/fa),(xs/fa));
for i=1:(xs/fa)
for j=1:(ys/fa)
imt(i,j) = ima(i*fa,j*fa);
end
end
else if factor>0 %amplify th image
for i=1:(xs*factor)
for j=1:(ys*factor)
imt(i,j) = ima(ceil(i/factor),ceil(j/factor));
end
end
else
imt = ima;
end
end
return;
最近邻插值算法放大图像
双线性插值算法
最近邻插值算法只是通过源图像一个点的像素值来填充目标图像的值,这在放大倍数大了以后造成失真。双线性插值算法通过计算源图像四个点的像素值来填充目标像素,并且采用加权计算的方法使得四个点对填充点的像素都贡献不一样,这其中也顺带了平滑滤波的效果,使得插值后的图像看起来稍微模糊一点。在计算量上双线性插值算法比最近邻插值算法大。
对于一个目标像素,试着坐标反向变化得到的是浮点坐标(i+u,j+v),其中i,j均为浮点坐标的整数部分,u,v均为浮点数的小数部分,这个像素f(i+u,j+v)可由原图像的四个坐标(i,j),(i+1,j+1),(i+1.j)(i,j+1)来获得。
![这里写图片描述](https://img-blog.csdn.net/20170331165059203?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2lsZW5jZTIwMTU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
现在假如目标图的象素坐标为(1,1),那么反推得到的对应于源图的坐标是(0.75 , 0.75),
这其实只是一个概念上的虚拟象素,实际在源图中并不存在这样一个象素,那么目标图的象素(1,1)的取值不能够由这个虚拟象素来决定,而只能由源图的这四
个象素共同决定:(0,0)(0,1)(1,0)(1,1),而由于(0.75,0.75)离(1,1)要更近一些,那么(1,1)所起的决定作用更大一
些,这从公式1中的系数uv=0.75×0.75就可以体现出来,而(0.75,0.75)离(0,0)最远,所以(0,0)所起的决定作用就要小一些,
公式中系数为(1-u)(1-v)=0.25×0.25也体现出了这一特点
双线性插值算法matlab简易实现
function img=change_size(imgpath,xs,ys)
% this function is design to amplify or shink an image
f=imread(imgpath);
[m,n]=size(f);
x_rate=xs/m;
y_rate=ys/n;
img=zeros(xs,ys);
if x_rate>=1 && y_rate>=1 % amplify imge in x and y axis
for i=1:xs
for j=1:ys
srcx=i/x_rate;
srcy=j/y_rate;
srcx_int=floor(srcx);
srcx_decimal=srcx-srcx_int;
srcy_int=floor(srcy);
srcy_decimal=srcy-srcy_int;
if srcx_int==0
srcx_int=1;
else if srcx_int>=m
srcx_int=m-1;
end
end
if srcy_int==0
srcy_int=1;
else if srcy_int>=n
srcy_int=n-1;
end
end
img(i,j)=srcx_decimal*srcy_decimal*f(srcx_int+1,srcy_int+1)+(1-srcx_decimal)*(1-srcy_decimal)*f(srcx_int,srcy_int)...
+srcx_decimal*(1-srcy_decimal)*f(srcx_int,srcy_int+1)+(1-srcx_decimal)*srcy_decimal*f(srcx_int+1,srcy_int);
end
end
end
if x_rate<=1 && y_rate<=1 % amplify imge in x and y axis
for i=1:xs
for j=1:ys
srcx=i/x_rate;
srcy=j/y_rate;
srcx_int=floor(srcx);
srcx_decimal=srcx-srcx_int;
srcy_int=floor(srcy);
srcy_decimal=srcy-srcy_int;
if srcx_int==0
srcx_int=1;
else if srcx_int>=m
srcx_int=m-1;
end
end
if srcy_int==0
srcy_int=1;
else if srcy_int>=n
srcy_int=n-1;
end
end
img(i,j)=srcx_decimal*srcy_decimal*f(srcx_int,srcy_int)+(1-srcx_decimal)*(1-srcy_decimal)*f(srcx_int+1,srcy_int+1)...
+srcx_decimal*(1-srcy_decimal)*f(srcx_int+1,srcy_int)+(1-srcx_decimal)*srcy_decimal*f(srcx_int,srcy_int+1);
end
end
end
img=uint8(img);
end
其中该代码功能局限性很大,而且我发现经过双线性插值后的图像有锯齿状的像素块,分析很久没发现原因
双线性插值算法放大图像
三次卷积就引入更多领近的像素来计算像素值,精度当然很高,但是计算量也大很多。
降低图像灰度级
我们知道,图像分很多灰度级,灰度级越大,所呈现的图像月丰富,所能表现的颜色跨度也越大。
这儿本文以8bits的灰度图像为例子,实现灰度级的降低
function changereduce_factor(imgpath,reduce_factor)
% Write a computer program capable of reducing the number of intensity levels in an image from 256 to 2,
% in integer powers of 2. The desired number of intensity levels needs to be a variable input to your program.
f = imread(imgpath);
if reduce_factor<0
reduce_factor=0
else if reduce_factor>8
reduce_factor=8
end
end
dfactor=uint8(2^reduce_factor);
f_trans=(f/dfactor)*dfactor;
subplot(1,2,1);
imshow(f);
subplot(1,2,2);
imshow(f_trans);
end
本实验是以2的幂次方来降低图像的灰度。
dfactor=uint8(2^reduce_factor);
f_trans=(f/dfactor)*dfactor;
是先根据降低的灰度级除以原始图像像素大小,得到整数,去除小数部分。然后在乘以降低的灰度级来量化图像,就得到了降低灰度级后的图像。