• 使用双线性插值法放大图像(matlab实现)


    双线性插值的概念及公式可以参考百度,这里仅对算法原理进行简单的说明:

    双线性插值计算公式:

    f(i+u,j+v) = (1-u)(1-v)f(i,j)+u(1-v)f(i+1,j)+(1-u)vf(i,j+1)+ uvf(i+1,j+1)  

    这个公式表明了如何利用矩阵中的四个像素值计算新的像素值,这些新的像素值就组成了放大后的图像。

    下图是如何将3x3的图像放大为4x4的图像:

    原图像表示为3x3的矩阵(像素值处在黑线的交叉点上),如何计算4x4矩阵的值呢?(像素值处在红色虚线交叉点及红线与黑线的交点上)

    比如新图像B的第一列与原图像A的第一列的对应关系是:

    B(1,1) = A(1,1)

    B(1,2) = A(1,1.66667)

    B(1,3) = A(1,2.33334)

    B(1,4) = A(1,3.00001)

    应用上面的公式,实际上就是用A的含有小数点的位置的像素值来计算B的像素值,但含有小数点位的像素是不存在的,这里称为虚拟位置。

    用原图像A的值就能计算出放大后B的值,是不是很神奇?

    实际上可以这样认为:双线性插值就是把放大后的图像再压缩到原来图像的尺寸大小,计算原图像中虚拟的像素值,等同于计算放大后图像的像素值,

    对于本例来说,B图像的步长相当于A图像步长的(3-1)/(4-1)=0.66667倍。下面我们就可以利用这个比率来对应B中像素位置与A中虚拟像素位置的关系。

    B(1,1) = A(1,1)                    (1-1)*0.66667+1=1

    B(1,2) = A(1,1.66667)         (2-1)*0.66667+1=1.66667

    B(1,3) = A(1,2.33334)         (3-1)*0.66667+1=2.33334

    B(1,4) = A(1,3.00001)         (4-1)*0.66667+1=3.00001

    根据上面的对应关系,我们就可以用代码实现了。

    现在还有一个问题:

    我们计算虚拟像素值是需要周围四个原像素值,比如上列中的(下图中红圈圈住的部分)

    A(1,3) = (1-0)(1-0)A(1,3) + (1-0)0A(1,4) + 0(1-0)A(2,3) + 00A(2,4)

    显然这里的A(1,4)和A(2,4)是无法索引到得,因为原图像是3x3的矩阵。

    为了解决这个问题,在A的最后一行,与最后一列分别加上0,这样A就变成了4x4的矩阵。

    图示中扩展的0行0列的元素位置用红色的坐标标示,红色斜箭头把需要用到扩展A矩阵的虚拟像素点位置都标了出来。

    实验结果:

    原图像:

    放大四倍后的图像:


     

    代码实现:

    主程序代码:

    clear ; close all; clc
    image = imread('bird.png');  %载入图像的值
    r = image(:,:,1);     %由于真彩图是红蓝绿三个像素的叠加
    g = image(:,:,2);     %这里把r,g,b分离出来单独调用函数计算
    b = image(:,:,3);     %计算完成后再进行组装
    %这里需要手动设置放大的倍数
    w = 4;   %w放大的是竖直方向
    l = 4;   %l放大的是水平方向
    
    r = extenRGB(r,w,l);  %调用函数计算放大后的r值
    g = extenRGB(g,w,l);  %调用函数计算放大后的g值
    b = extenRGB(b,w,l);  %调用函数计算放大后的b值
    %下面把计算完成后的rgb再组装起来
    outRGB(:,:,1) = r;
    outRGB(:,:,2) = g; 
    outRGB(:,:,3) = b;
    
    outRGB = uint8(outRGB);%格式转换,否则无法显示
    
    imshow(outRGB);        %显示放大后的图像
     
     

     主程序调用的函数:

    %像素放大计算函数 extenRGB()
    function Output = extenRGB(A,w,l)
    
    % A矩阵分别代表r,g,b矩阵
    [m,n] = size(A);      %读取A的行和列 
    A = [A;zeros(1,n)];   %在A的最后一行加入两行0
    A = [A zeros(m+1,1)]; %在A的最后一列加入两列0
    %这样A就变成(m+1)x(n+1)的矩阵,这是为了解决索引A矩阵时的边界溢出问题
    
    ini_u = (m-1)/(w*m-1); %步长比,如果把原来的一步A(1,1)到A(2,1)看做1,那么计算放大后的
    ini_v = (n-1)/(l*n-1); %图像B(2,1)相当于计算A(1+ini_u,1),即每步加ini_u
             
    
    Output = zeros(w*m,l*n);            %初始化输出矩阵
    for j = 1:l*n;                      %左边两个语句的功能是:z_u,z_v向左取整,u,v取小数,原理如下
        z_v = floor((j-1)*ini_v+1);     %比如A为3x3的矩阵,要放大为Output是4x4大小,即放大了4/3倍, 
          v = (j-1)*ini_v+1 - z_v;      %新的一步的距离相当于原来的(3-1)/(4-1)=0.66667
        for i = 1:w*m;                  %Output(1,1) = A(1,1)       %(1-1)*0.66667+1=1
            z_u = floor((i-1)*ini_u+1); %Output(1,2) = A(1,1.66667) %(2-1)*0.66667+1=1.66667
              u = (i-1)*ini_u+1 - z_u;  %Output(1,3) = A(1,2.33334) %(3-1)*0.66667+1=2.33334
                                        %Output(1,4) = A(1,3.00001) %(4-1)*0.66667+1=3.00001
                                        
                                       
    
    %===================下面是双线性插值的代码实现================================   
            Output(i,j) = (1 - u)*(1 - v)*A(z_u,     z_v    ) + ...
                          (1 - u)* v     *A(z_u,     z_v + 1) + ...
                           u     *(1 - v)*A(z_u + 1, z_v    ) + ...
                           u     * v     *A(z_u + 1, z_v + 1);
        end
    end
           
  • 相关阅读:
    localStorage_留言板(储存功能)
    localStorage_留言板01
    localStorage的存储功能
    html表单笔记
    jdbc连接数据库Mysql实例
    (二)SpringMVC学习笔记-HelloWorld
    (一)SpringMVC学习笔记-概述
    animation的相关属性:
    text-transform的各种属性
    ajax请求的时候get 和post方式的区别:
  • 原文地址:https://www.cnblogs.com/bigpo/p/4126806.html
Copyright © 2020-2023  润新知