图像插值技术——双线性插值法

在图像处理中,如果需要对图像进行缩放,一般可以采取插值法。最常用的就是双线性插值法,为了理解图像插值,我们首先了解什么是一维线性插值。

数学角度的线性插值

一维线性插值

假设有一个一元函数 \(y = f(x)\) , 已知曲线上的两点,\(A\)\(B\) 的坐标分别为 \((x_0 , y_0)\)\((x_1, y_1)\) 。现在要在\(A\)\(B\) 之间通过插值计算出一个点 \(P\) ,若已知 \(P\)点的横坐标 \(x\),如何求出 \(P\)点的纵坐标 \(y\) ?

这里我们的插值之所以叫做线性插值,就是因为我们假定了 \(P\) 点落在 \(A\) 点和 \(B\) 点的连线上,使得他们的坐标之间满足线性关系。所以,根据初中的知识,可以得到下面的等式:

\[{{y - {y_0}} \over {{y_1} - {y_0}}} = {{x - {x_0}} \over {{x_1} - {x_0}}} \]

这里我们令:

\[\alpha = {{x - {x_0}} \over {{x_1} - {x_0}}} \]

于是,我们可以得到\(P\)点的纵坐标 \(y\) 的表达式:

\[y = \left( {1 - \alpha } \right){f(x_0)} + \alpha {f(x_1)} \]

二维线性插值

一维线性插值可以扩展到二维的情况。

假设有一个二元函数 \(z = f(x,y)\) , 已知曲面上的四点,\(A\)\(B\)\(C\)\(D\)的坐标分别为 \((x_0 , y_0)\)\((x_1, y_0)\)\((x_1, y_1)\)\((x_0, y_1)\) 。现在要在\(A\)\(B\)\(C\)\(D\)之间通过插值计算出一个点 \(P\) ,若已知 \(P\)点的坐标 \((x,y)\),如何求出 \(P\)点的函数值坐标 \(z\) ?

这里我们依旧可以仿照一维线性插值,进行计算。

假设先计算 \(y\) 轴方向的插值点 \(P_0\)\(P_1\) ,则根据上面的推导过程,且令

\[\alpha = {{y - {y_0}} \over {{y_1} - {y_0}}} \]

则, \(P_0\) 的取值 \(z_0\)为:

\[z_0 = \left( {1 - \alpha } \right){f(x_0,y_0)} + \alpha {f(x_0,y_1)} \]

\(P_1\) 的取值 \(z_1\)为:

\[z_1 = \left( {1 - \alpha } \right){f(x_1,y_0)} + \alpha {f(x_1,y_1)} \]

再计算 \(x\) 轴方向的插值点 \(P\),令

\[\beta = {{x - {x_0}} \over {{x_1} - {x_0}}} \]

\(P\) 的取值 \(z\)为:

\[z = \left( {1 - \beta } \right){z_0} + \beta {z_1} \]

整理得到下面的式子:

\[\eqalign{ & z = \left( {1 - \beta } \right)\left[ {\left( {1 - \alpha } \right)f\left( {{x_0},{y_0}} \right) + \alpha f\left( {{x_0},{y_1}} \right)} \right] + \beta \left[ {\left( {1 - \alpha } \right)f\left( {{x_1},{y_0}} \right) + \alpha f\left( {{x_1},{y_1}} \right)} \right] \cr & \;\;{\kern 1pt} = \left( {1 - \beta } \right)\left( {1 - \alpha } \right)f\left( {{x_0},{y_0}} \right) + \left( {1 - \beta } \right)\alpha f\left( {{x_0},{y_1}} \right) + \beta \left( {1 - \alpha } \right)f\left( {{x_1},{y_0}} \right) + \beta \alpha f\left( {{x_1},{y_1}} \right) \cr} \]

小结

由一维线性插值过渡到二维线性插值,我们发现,二者在表达式上有相似的规律:

一维线性插值:

\[\left\{ {\matrix{ {y = f\left( x \right)} \hfill \cr {\alpha = {{x_p - {x_0}} \over {{x_1} - {x_0}}}} \hfill \cr {{y_p} = \left( {1 - \alpha } \right)f\left( {{x_0}} \right) + \alpha f\left( {{x_1}} \right)} \hfill \cr } } \right. \]

二维线性插值:

\[\left\{ {\matrix{ {z = f\left( {x,y} \right)} \hfill \cr {\alpha = {{{x_p} - {x_0}} \over {{x_1} - {x_0}}},\beta = {{{y_p} - {y_0}} \over {{y_1} - {y_0}}}} \hfill \cr {{z_p} = \left( {1 - \beta } \right)\left( {1 - \alpha } \right)f\left( {{x_0},{y_0}} \right) + \left( {1 - \beta } \right)\alpha f\left( {{x_0},{y_1}} \right) + \beta \left( {1 - \alpha } \right)f\left( {{x_1},{y_0}} \right) + \beta \alpha f\left( {{x_1},{y_1}} \right)} \hfill \cr } } \right. \]


图像中的双线性插值

我们可以用函数来表示一幅图像(假设为单通道)。如下图所示,假设有一幅图,其尺寸为3×3大小,每个像素点对应一个灰度值(0~255),以图像的左上角为坐标原点,横向为 \(x\) 轴,纵向为 \(y\) 轴,则图像的表达式可以表达为:

\[f(x,y) \]

每个像素点的灰度值 \(z\) 由横纵坐标唯一确定,即 \(z=f(x,y)\)

假设需要将图片进行尺寸缩放,则可以利用前面所提到的双线性插值法进行变换。

这里我们定义原始的图片为 src ,其宽度为 src_width, 高度为 src_height,通道数为 channel

缩放的目标图片为 dst,其宽度为 dst_width, 高度为 dst_height, 通道数与原始图片一样,为channel

利用双线性插值来进行图像的缩放步骤如下:

  • 计算目标图片与原始图片之间的缩放因子(宽度、高度方向)
  • 利用缩放因子,由目标图片像素位置反推回原始图片中的虚拟像素位置
  • 由虚拟像素位置找到宽度和高度方向相邻的四个像素点
  • 由四个像素点进行双线性插值计算,得出目标图像中的像素值

由于图片像素的位置一格表示一个像素,因此,在前面的公式中,相邻的点之间坐标在相同方向的差值为1。

基于Matlab的图片双线性插值

close all
clc
clear

% 读取原始图像,并转换为 double 类型
src = imread('lena.jpg');
src = im2double(src);

% 读取图像尺寸信息
[src_width, src_height,channel] = size(src);

% 目标图像尺寸
dst_width = 50;
dst_height = 50;


% 计算缩放因子
horFactor = src_width / dst_width;
verFactor = src_height / dst_height;

% 初始化矩阵
dst = zeros(dst_width,dst_height,channel);

for i = 1:channel
    for j = 1:dst_width
        
        x0 = j*horFactor;           % 计算虚拟像素值位置
        x1 = ceil(x0);              % 取其左侧临近的位置
        x2 = min([x1+1,src_width]); % 取其右侧侧临近的位置,用 min 防止超出原始图片边界
        
        beta = x0 - x1;             % 公式中的 beta
        
        
        for k = 1:dst_height
            
            y0 = k*verFactor;           % 计算虚拟像素值位置
            y1 = ceil(y0);              % 取其左侧临近的位置
            y2 = min([y1+1,src_height]);% 取其右侧侧临近的位置,用 min 防止超出原始图片边界
            
            alpha = y0 - y1;             % 公式中的 alpha
            
            % 双线性插值求出该位置的像素值
            dst(j,k,i) = (1-beta)*(1-alpha)*src(x1,y1,i) + ...
                         (1-beta)*alpha*src(x1,y2,i) + ...
                         beta*(1-alpha)*src(x2,y1,i) + ...
                         beta*alpha*src(x2,y2,i);
            
        end
    end
end


% 处理前后图片对比
subplot(1,2,1)
imshow(src)
subplot(1,2,2)
imshow(dst)

缩小图片

利用代码 可以对图像进行缩放 200×200 → 50×50

放大图片

利用代码 可以对图像进行缩放 200×200 → 600×600

猜你喜欢

转载自www.cnblogs.com/gshang/p/12968496.html