Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于图像处理中的插值算法(Matlab语言描述) #1

Open
WarpPrism opened this issue Nov 13, 2016 · 0 comments
Open

关于图像处理中的插值算法(Matlab语言描述) #1

WarpPrism opened this issue Nov 13, 2016 · 0 comments

Comments

@WarpPrism
Copy link
Owner

数字图像处理的第一次作业就是用图像的插值算法实现图片的放缩,在网上查了一些资料后,总结如下:

首先我们定义几个变量:

- 原图矩阵: Source
- 目标图矩阵: Destination
- 宽度缩放比: ratioW
- 高度缩放比: ratioH

先得到原图的宽和高

Source = imread('src.png');
[srcM, srcN] = size(Source);

接着根据下面的公式计算出目标图的宽和高:

ratioW = dstM / srcM;
ratioH = dstN / srcN;

新建目标图,根据目标图的大小建立一个空的Matrix,记作M

Destination = zeros(dstM, dstN);
M = Destination;

然后要对M中的每个点赋值,即所谓的插值运算,这个值从哪里来呢?当然是原图。

现在 设M矩阵的坐标点为(dx, dy),则它对应的原图坐标(sx, sy)满足:

dx / sx = dstM / srcM;
dy / sy = dstN / srcN;

这样我们就能求出

(sx, sy) = (dx * srcM / dstM, dy * srcN / dstN);

到此,我们就把目标图中的坐标点映射到原图中去了

但是这个坐标点不一定是整数,假如(2, 0) 映射的结果为 (0.75, 0),这显然是不科学的,怎么办呢?
第一种方法,四舍五入 得到 (1, 0),然后把原图中(1, 0)点的像素值赋给目标图的(2, 0)位置即可:

fd(2, 0) = fs(1, 0);

这种放大图像的方法就叫做 最临近插值算法,这是一种最基本、最简单的图像缩放算法,效果也是最不好的,放大后的图像有很严重的马赛克,缩小后的图像有很严重的失真。

另一种算法就是双线性插值算法,它的失真情况会好很多。

算法思路是:
对于一个目的像素,映射后得到的浮点坐标为(i+u,j+v),
(其中i、j均为浮点坐标的整数部分,u、v为浮点坐标的小数部分,是取值[0,1)区间的浮点数),则这个像素得值 f(dx,dy) 可由原图像中坐标为 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所对应的周围四个像素的值决定,即:

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

这里我们就可以由原图中的 4 个像素点推出了目标图中1个像素点,最后遍历目标图,我们就能实现图片的放缩了。

双线性插值算法代码如下所示:

% Bilinear Function
function [ output_img ] = scale( input_img, Size )
    % Using bilinear algorithm to change the SIZE of input_img.
    dstM = Size(1);
    dstN = Size(2);
    [srcM srcN]=size(input_img);
    output_img = zeros(dstM, dstN);
    for i = 1:dstM - 1
        for j = 1:dstN - 1
            src_i = i * (srcM / dstM);
            src_j = j * (srcN / dstN);
            int_i = fix(src_i);
            int_j = fix(src_j);
            u = src_i - int_i;
            v = src_j - int_j;
            if int_i == 0
                int_i = int_i + 1;
            end
            if int_j == 0
                int_j = int_j + 1;
            end
            output_img(i,j)=(1-u)*(1-v)*input_img(int_i,int_j)+(1-u)*v*input_img(int_i,int_j+1)
                            +u*(1-v)*input_img(int_i+1,int_j)+u*v*input_img(int_i+1,int_j+1);
        end
    end
    output_img = uint8(output_img);
    figure,imshow(input_img)
    axis on
    figure,imshow(output_img)
    axis on
end

% call function scale()
close all
clear all
clc

input_img = imread('test.png')
size = [100, 100]
output_img = scale(input_img, size)
imtool(output_img)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant