matlab图像内插
- 最近邻插值
- 双线性插值
- 双三次插值
- 总结
 
最近邻插值
目标各像素点的灰度值代替源图像中与其最邻近像素的灰度值
 参考博客
 假设一个2X2像素的图片采用最近邻插值法需要放大到4X4像素的图片,右边该为多少?
 
 最近邻插值法坐标变换计算公式:
  
      
       
        
        
          s 
         
        
          r 
         
        
          c 
         
        
          X 
         
        
          = 
         
        
          d 
         
        
          s 
         
        
          t 
         
        
          X 
         
        
          ∗ 
         
        
          ( 
         
        
          s 
         
        
          r 
         
        
          c 
         
        
          W 
         
        
          i 
         
        
          d 
         
        
          t 
         
        
          h 
         
        
          / 
         
        
          d 
         
        
          s 
         
        
          t 
         
        
          W 
         
        
          i 
         
        
          d 
         
        
          t 
         
        
          h 
         
        
          ) 
         
        
       
         srcX=dstX*(srcWidth/dstWidth) 
        
       
     srcX=dstX∗(srcWidth/dstWidth)
  
      
       
        
        
          s 
         
        
          r 
         
        
          c 
         
        
          Y 
         
        
          = 
         
        
          d 
         
        
          s 
         
        
          t 
         
        
          Y 
         
        
          ∗ 
         
        
          ( 
         
        
          s 
         
        
          r 
         
        
          c 
         
        
          H 
         
        
          e 
         
        
          i 
         
        
          g 
         
        
          h 
         
        
          t 
         
        
          / 
         
        
          d 
         
        
          s 
         
        
          t 
         
        
          H 
         
        
          e 
         
        
          i 
         
        
          g 
         
        
          h 
         
        
          t 
         
        
          ) 
         
        
       
         srcY=dstY*(srcHeight/dstHeight) 
        
       
     srcY=dstY∗(srcHeight/dstHeight)
  
     
      
       
       
         d 
        
       
         s 
        
       
         t 
        
       
         X 
        
       
      
        dstX 
       
      
    dstX与 
     
      
       
       
         d 
        
       
         s 
        
       
         t 
        
       
         Y 
        
       
      
        dstY 
       
      
    dstY为目标图像的某个像素的横纵坐标, 
     
      
       
       
         d 
        
       
         s 
        
       
         t 
        
       
         W 
        
       
         i 
        
       
         d 
        
       
         t 
        
       
         h 
        
       
      
        dstWidth 
       
      
    dstWidth与 
     
      
       
       
         d 
        
       
         s 
        
       
         t 
        
       
         H 
        
       
         e 
        
       
         i 
        
       
         g 
        
       
         h 
        
       
         t 
        
       
      
        dstHeight 
       
      
    dstHeight为目标图像的长与宽;
  
     
      
       
       
         s 
        
       
         r 
        
       
         c 
        
       
         W 
        
       
         i 
        
       
         d 
        
       
         t 
        
       
         h 
        
       
      
        srcWidth 
       
      
    srcWidth与 
     
      
       
       
         s 
        
       
         r 
        
       
         c 
        
       
         H 
        
       
         e 
        
       
         i 
        
       
         g 
        
       
         h 
        
       
         t 
        
       
      
        srcHeight 
       
      
    srcHeight为原图像的宽度与高度。
  
     
      
       
       
         s 
        
       
         r 
        
       
         c 
        
       
         X 
        
       
      
        srcX 
       
      
    srcX, 
     
      
       
       
         s 
        
       
         r 
        
       
         c 
        
       
         Y 
        
       
         v 
        
       
      
        srcYv 
       
      
    srcYv为目标图像在该点 
     
      
       
       
         ( 
        
       
         d 
        
       
         s 
        
       
         t 
        
       
         X 
        
       
         , 
        
       
         d 
        
       
         s 
        
       
         t 
        
       
         Y 
        
       
         ) 
        
       
      
        (dstX,dstY) 
       
      
    (dstX,dstY)对应的原图像的坐标。
 
 右图为经过放大后的目标图像,?处的坐标为 
     
      
       
       
         ( 
        
       
         3 
        
       
         , 
        
       
         2 
        
       
         ) 
        
       
      
        (3,2) 
       
      
    (3,2),根据公式计算得到
  
     
      
       
       
         s 
        
       
         r 
        
       
         c 
        
       
         X 
        
       
         = 
        
       
         3 
        
       
         ∗ 
        
       
         ( 
        
       
         2 
        
       
         / 
        
       
         4 
        
       
         ) 
        
       
         = 
        
       
         1.5 
        
       
         , 
        
       
         s 
        
       
         r 
        
       
         c 
        
       
         Y 
        
       
         = 
        
       
         2 
        
       
         ∗ 
        
       
         ( 
        
       
         2 
        
       
         / 
        
       
         4 
        
       
         ) 
        
       
         = 
        
       
         1 
        
       
      
        srcX=3*(2/4)=1.5,srcY=2*(2/4)=1 
       
      
    srcX=3∗(2/4)=1.5,srcY=2∗(2/4)=1;
 故?处的像素应该为原图像中的 
     
      
       
       
         ( 
        
       
         1.5 
        
       
         , 
        
       
         1 
        
       
         ) 
        
       
      
        (1.5,1) 
       
      
    (1.5,1)像素的值,但是像素坐标没有小数,一般采用四舍五入取最邻,所以最终的结果为 
     
      
       
       
         ( 
        
       
         2 
        
       
         , 
        
       
         1 
        
       
         ) 
        
       
      
        (2,1) 
       
      
    (2,1),对应原图像的橙色。
 其他类比得到放大后的图像:
 
f=imread('lena.jpg');
N=0.8;
[row,col,color]=size(f);
row_n=round(row*N);%行取整函数
col_n=round(col*N);%列取整函数
%新图像初始化
fnew=zeros(row_n,col_n,color,class(f));
%采用最近邻放缩
%使用class获得原图像的数据类型,使得新图像数据类型与原图像保持一致
for i=1:row_n
    for j=1:col_n
        for n=1:color
            m=round(i/N);%对应原理中的公式
            k=round(j/N);%m,k为新像素点
            if m<1%处理不理想值的情况
                m=1;
            end
            if k<1
                k=1;
            end
            if m>row
                m=row;
            end
            if k>col
                k=col;
            end
            fnew(i,j,n)=f(m,k,n);
        end
    end
end
figure;
imshow(f);
title('原图');
figure;
imshow(fnew)
title('缩小后的图片');

 
双线性插值
根据待求点P相邻最近4个点的像素值,计算出P点的像素值。
 
 已知Q12,Q22,Q11,Q21,但是要插值的点为P点,这就要用双线性插值了,首先在x轴方向上,对R1和R2两个点进行插值,这个很简单,然后根据R1和R2对P点进行插值,这就是所谓的双线性插值。
 
 得到P点的像素 f(x, y)
clear
f=imread('lena.jpg');
N=0.8;
[row,col,color]=size(f);
row_n=round(row*N);%行取整函数
col_n=round(col*N);%列取整函数
%新图像初始化
fnew=zeros(row_n,col_n,color,class(f));
%采用双线性放缩
%使用class获得原图像的数据类型,使得新图像数据类型与原图像保持一致
for i=1:row_n
    for j=1:col_n
        for n=1:color
            m=round(i/N);%对应原理中的公式
            k=round(j/N);%m,k为新像素点
            s=m+1;
            q=k+1;
            %处理不理想值的情况
            if m<1
                m=1;
            end
            if k<1
                k=1;
            end
            if m>row
                m=row;
            end
            if k>col
                k=col;
            end
            if s>row
                m=row-1;
            end
            if q>row;
                k=col-1;
            end
            u = i/N-floor(i/N); %求取水平方向上的权重
            v = j/N-floor(j/N); %求取垂直方向上的权重
            fnew(i,j,n) = u*v*f(m,k,n)+(1-u)*v*f(m+1,k,n)+u*(1-v)*f(m,k+1,n)+(1-u)*(1-v)*f(m+1,k+1,n);
            
        end
    end
end
figure;
imshow(f);
title('原图');
figure;
imshow(fnew)
title('缩小后的图片');

 
双三次插值
参考博客
在这种方法中,插值点 (x, y) 的像素灰度值 f(x, y) 通过矩形网格中 最近的十六个采样点的加权平均 得到,而 各采样点的权重由该点到待求插值点的距离确定,此距离包括 水平和竖直 两个方向上的距离。
 
上图是一个二维图像的双三次插值俯视示意图。设待求插值点坐标为 (i+u, j+v),已知其周围的 16 个像素坐标点 (网格) 的灰度值,还需要计算 16 个点各自的权重。
 以像素坐标点 (i, j) 为例,因为该点在 y 轴和 x 轴方向上与待求插值点 (i+u, j+v) 的距离分别为 u 和 v,所以的权重为 w(u) × w(v),其中 w(·) 是插值权重核 (可以理解为定义的权重函数)。
 同理可得其余 15 个像素坐标点各自的权重。那么,待求插值点 (i+u, j+v) 的灰度值 f(i+u, j+v) 将通过如下计算得到:
 
      
       
        
        
          f 
         
        
          ( 
         
        
          i 
         
        
          + 
         
        
          u 
         
        
          , 
         
        
          j 
         
        
          + 
         
        
          v 
         
        
          ) 
         
        
          = 
         
        
          A 
         
        
          × 
         
        
          B 
         
        
          × 
         
        
          C 
         
        
       
         f(i+u,j+v)=A×B×C 
        
       
     f(i+u,j+v)=A×B×C
 
 插值权重核 w(·) 为:

 推荐参考博客
 下面的代码争对的是二维图像的双三次插值处理,若加上彩色会有三个通道,在矩阵转置中会比较麻烦,所以这里只用了两个图像通道。
%双三次插值具体实现
clc,clear;
tic; % calculate running time
fff=imread('lena.jpg'); 
ff =rgb2gray(fff);%转化为灰度图像
[row,col]=size(ff);               %将图像隔行隔列抽取元素,得到缩小的图像f
row_n=row/2;
col_n=col/2;
f =zeros(row_n,col_n);
for i=1:row_n
   for j=1:col_n
     f(i,j)=ff(2*i,2*j);
   end
end
 
k=2;                       %设置放大缩小,相对于缩小后图像进行处理
row_n1=round(k*row_n);
col_n1=round(k*col_n);
a=f(1,:);
c=f(row_n,:);             %将待插值图像矩阵前后各扩展两行两列,共扩展四行四列
b=[f(1,1),f(1,1),f(:,1)',f(row_n,1),f(row_n,1)];
d=[f(1,col_n),f(1,col_n),f(:,col_n)',f(row_n,col_n),f(row_n,col_n)];
a1=[a;a;f;c;c];
b1=[b;b;a1';d;d];
f1=double(b1');
fnew =zeros(row_n1,col_n1);
for i=1:row_n1                 %利用双三次插值公式对新图象所有像素赋值
    u=rem(i,k)/k;
    i1=floor(i/k)+2;
    A=[sw(1+u) sw(u) sw(1-u) sw(2-u)];  
  for j=1:col_n1
     v=rem(j,k)/k;
     j1=floor(j/k)+2;
     C=[sw(1+v);sw(v);sw(1-v);sw(2-v)];
     B=[f1(i1-1,j1-1) f1(i1-1,j1) f1(i1-1,j1+1) f1(i1-1,j1+2)
       f1(i1,j1-1)   f1(i1,j1)  f1(i1,j1+1)   f1(i1,j1+2)
       f1(i1+1,j1-1)   f1(i1+1,j1) f1(i1+1,j1+1) f1(i1+1,j1+2)
       f1(i1+2,j1-1) f1(i1+2,j1) f1(i1+2,j1+1) f1(i1+2,j1+2)];
     fnew(i,j)=(A*B*C);
   end
end
gfnew=uint8(fnew); 
figure,imshow(uint8(f));title('缩小的图像');             %显示缩小的图像 
figure,imshow(ff);title('原图');               %显示原图像
figure,imshow(gfnew);title('双三次插值放大的图像');     %显示插值后的图像
toc;

历时 1.267243 秒。

总结
最近邻内插简单但容易产生不想要的人为失真,如严重的直边失真。
 双线性内插的结构比最近邻结果好很多,由4个最近邻的像素得出,但计算量随之增大。
 复杂度最高的是双三次内插,由16个最近邻的像素得出,但花费时间会更久。













![[python][vpython]用vpython实现小球砸弹簧代码](https://img-blog.csdnimg.cn/f339354c25964d1c990b16054819ee2d.jpeg)




