zoukankan      html  css  js  c++  java
  • [数字图像处理](六)插值运算

    参考文章

    (1条消息) 几种常用的插值和分段插值方法Matlab算法实现_树莓、的博客-CSDN博客_分段线性插值matlab

    MATLAB 图像的插值算法2:最近邻插值_Effend的博客-CSDN博客_matlab最近邻插值

    [数字图像处理](六)插值运算

    前言

    ​ 本文章介绍的几种算法都是用变化后的坐标(((n*R || m*R)R 为变化率(如1.5))) 来计算映射到原始图像的位置,有很多博客和wiki都介绍了这些算法的数学原理,这里就不做介绍了就是数学不好。

    ​ 本文章就matlab代码,来解释算法的执行逻辑,以便于更好的理解算法的实际思想。

    1____最近邻插值法

    基本思想

    下文会用到的标记

    • transim()变换后的图像

    • grayim()变换之前的图像

    • n,m——grayim的大小,c,l——transim的大小

    • R变换率——(n*R = c,m*R = l)


    ​ 最近邻插值法,本质上就是变换后图像的坐标等比映射到原图像取值

    $ transim(i,j) = grayim( round(i/R),round(j/R) ) $

    实现代码

    %%	nearest_neighbor
    clc;
    clear all;
    close all;
    
    rgbim = imread('p2.png');
    grayim = rgb2gray(rgbim);
    [n,m] = size(grayim);
    figure;
    imshow(grayim);
    
    %%  设置变换率
    R = 2.8;
    n = round(n*R);%    四舍五入
    m = round(m*R);
    
    %%   变换
    transim = zeros(n,m,class(grayim));%	class的作用的把transim的数据类型变成和grayim一直的数据类型
    
    for i = 1:1:n
        for j = 1:1:m
            x = round(i/R)	;%	映射到原图像
            y = round(j/R);
            if x == 0		%	考虑到边界问题
                x = x + 1;
            end
            if y == 0
                y = y + 1;
            end
            %------------
            transim(i,j) = grayim(x,y);
        end
    end
    %%  输出图像
    figure;
    imshow(transim);
    imwrite(transim,'transim.png');
    
    

    2____双线性插值法

    前言

    ​ 我在学习了最近邻插值法之后,想学的是线性插值法,去了解了之后发现,这是一个处理一维图像的算法。在粗略的了解与思考之后发现其实也是可以做二维图像的,只不过说处理时只能参考横向偏移量,或者纵向偏移量,有一定的局限性。

    ​ 所以在这里我就直接跳过线性插值法,直接来说说双线性插值法

    基本思想

    ​ 如果知道线性插值法是如何处理的,那么双线性插值法也就明白了。

    ​ 同时双线性插值法也是最近邻插值法的优化,在最近邻插值法中,我们直接用等比缩放的映射值来充当变换图像的灰度值(详见上),这样就浪费了很多领域的信息,如果把领域的信息利用起来,是不是就可以在一定程度上提升画质呢(通过之前学习的各种优化来推到)?

    ​ 双线性插值法就是这样的思路,利用到了映射之后的领域信息,以及映射的比率来确定横纵上的偏移量,我这有系统的说,肯定很多小伙伴是云里雾里,但是看了下面的描述,再来看这段文字,必定茅塞顿开。


    双线性插值法

    1. 理解偏移量 (u,v)

      • 横向:(u = frac{i}{R} - floor(frac{i}{R}))

      • 纵向:(v = frac{i}{R}-floor(frac{j}{R}))

      如何理解这个偏移量呢?

      ​ 我们假设 $ i = 7,j = 131, R = 0.5 $

      ​ 那么(u = 3.5 - 3 = 0.5) 这个0.5就对应的是上图的u,从图像的意义来解释,这个值反应的是是这个映射坐标本质上是更靠近x还是x+1 (因为很有可能不同的i,在同一R的情况下,能得到相同的映射坐标x)那么在这个时候,有了u以及v这个偏移量,就能更好的反应出图像的映射关系,进而得到更真实的变化图像。

      ​ 同理,你也可以试着来设定一些y值来理解一下在纵向上的偏移量。

    2. 如果得到最终图像

      ​ 查看上图我们发现,我们运用的是3*3领域中的4个边角,从坐标的描述上我们就可以得到,下面的计算式子(如果看不懂的话,可以结合上面的图来分析)

      (transim(i,j) = u*v*grayim(x,y) + (1-u)*v*grayim(x+1,y) + u*(1-v)*grayim(x,y+1)+(1-u)*(1-v)*grayim(x+1,y+1);)

    实现代码

    %%  双线性插值法
    clc;
    close all;
    clear all;
    
    rgbim = imread('p2.png');
    grayim = rgb2gray(rgbim);
    
    figure;
    imshow(grayim);
    
    R = 0.4;    %   变换率
    [n,m] = size(grayim);
    ans = round(3/2)
    
    n = round(n*R); %   变换后的宽
    m = round(m*R); %   变换后的高
    
    %%  变换
    transim = zeros(n,m,class(grayim));
    
    for i = 1:1:n
        for j = 1:1:m
            x = round(i/R); %   映射到原图像的位置
            y = round(j/R); %   映射到原图像的位置
            if x == 0 
                x = x+1;    end
            if y == 0
                y = y +1;   end
            %-----------------求得偏移量
            u = i/R - floor(i/R);   %   水平
            v = j/R - floor(j/R);   %   垂直
            %    对于在边缘位置的图像用最近邻插值法
            if i >= n - R || j >= m - R;
                transim(i,j) = grayim(x,y);
            else transim(i,j) = u*v*grayim(x,y) + (1-u)*v*grayim(x+1,y) + u*(1-v)*grayim(x,y+1)+(1-u)*(1-v)*grayim(x+1,y+1);
            end
        end
    end
    %%  输出结果
    figure;
    imshow(transim);
    imwrite(transim,'BI.png');
    
    
    
  • 相关阅读:
    ORA-04013,CACHE 值必须小于CYCLE值;解决方案
    .net 调用WCF服务接收数据对象属性为空
    各JAVA JDK版本下载地址
    记录一次基于Echart的数据可视化平台开发
    Swiper轮播使用记录--一个页面有多个DIV区域使用swiper进行轮播
    Echart使用记录-动态设置series的时候,设置了color属性,但所有的柱状图显示灰白色
    记录一次SignalR服务的搭建注意事项
    C#关于ListBox绑定list,不会刷新数据的问题
    关于bootstrap-fileinput上传后删除选中上传的文件,回到最初的选择文件界面
    Oracle 数据库 alert日志及trace日志的清理
  • 原文地址:https://www.cnblogs.com/hoppz/p/14813576.html
Copyright © 2011-2022 走看看