图像插值常用于二维图像中的缩放,以及图像畸变校正。由于图像数据量一般都比较大,本文主要参考Cubic Convolution Interpolation for Digital Image Processing一文,实现并分析文中提出的三次卷积插值算法。三次卷积插值算法的精度介于现行插值和三次样条算法之间,但他才用卷积的方式,减少了计算量,而且在两个方向的插值是可分的,是高档图像软件中图像缩放常用的算法。
由于该算法在图像两个维度上是可分的,这里只介绍一维的三次卷积插值方法,在另一个维度上用同样的方法在做一次即可。下面介绍一维函数的三次卷积插值。
假设一维空间中的函数为 f f ,我们的插值函数为 g g ,那么对于每个插值点 xk x k ,有 g(xk)=f(xk) g ( x k ) = f ( x k ) 。对于等间距采样的的数据,许多插值函数可以表示为如下形式:
三次卷积 kernel k e r n e l 满足一下几个条件:
1. 对于三次卷积插值,卷积插值内核是定义在子区间 (−2,−1) ( − 2 , − 1 ) , (−1,0) ( − 1 , 0 ) , (0,1) ( 0 , 1 ) , (1,2) ( 1 , 2 ) ,在区间 (−2,2) ( − 2 , 2 ) 外,插值kernel为0。因此,式 (1) ( 1 ) 中用于计算插值函数的数据点减为4个。
2. 卷积核必须是对称函数,结合上一个条件,卷积核 u u 可以写成如下形式:
对于某个需要获得值的插值点 x x ,它肯定位于两个样本点 xj x j 和 xj+1 x j + 1 之间。令 s=(x−xj)/h s = ( x − x j ) / h ,有 (x−xk)/h=(x−xj+xj−xk)/h=s+j−k ( x − x k ) / h = ( x − x j + x j − x k ) / h = s + j − k 。因此,式 (1) ( 1 ) 可写为:
当 j=0或n−1(假设有n个数据点) j = 0 或 n − 1 ( 假 设 有 n 个 数 据 点 ) 时,式 (6) ( 6 ) 中的 c−1或cn c − 1 或 c n 无法通过采样的数据点获得,因此需要估计 c−1 c − 1 和 cn c n 的值。
为了保证 g(x) g ( x ) 在边界上也能以 o(h3) o ( h 3 ) 接近 f(x) f ( x ) ,通过类似1.2节中的方法可以得出:
双三次卷积插值的Matlab代码实现,其cubic_conv.m函数文件为:
function [ scaled_image ] = cubic_conv( input_image, scaled_sz)
% CUBIC_CONV Implement cubic convolution along x direction,
% then along y direction.
% input_image Input image.
% scaled_sz Size of output image.
% scaled_image Output image.
scaled_image_x = cubic_conv_x(input_image, scaled_sz(2));
scaled_image = cubic_conv_x(scaled_image_x', scaled_sz(1));
scaled_image = scaled_image';
end
function [ scaled_image_x ] = cubic_conv_x( input_image, scaled_sz_x )
%1. Compute the coordinates to be interpolated
org_sz = [size(input_image,1), size(input_image,2)];
x_org = (0:scaled_sz_x-1)/(scaled_sz_x-1)*(org_sz(2)-1);
x = zeros([1, scaled_sz_x, 4]);
x_org_dec = x_org - floor(x_org);
x(1,:,1) = cubic_kernel(x_org_dec + 1);
x(1,:,2) = cubic_kernel(x_org_dec);
x(1,:,3) = cubic_kernel(1 - x_org_dec);
x(1,:,4) = cubic_kernel(2 - x_org_dec);
X = repmat(x, org_sz(1), 1, 1);
%2. Compute the boudary data
col_neg_1 = input_image(:,3) - 3*input_image(:,2) + 3*input_image(:,1);
col_N_plus_1 = input_image(:,end-2) - 3*input_image(:,end-1) + 3*input_image(:,end);
extent_image = [col_neg_1, input_image, col_N_plus_1];
x_int = floor(x_org);
x_int(x_int >= org_sz(2)-1) = org_sz(2)-2;
% x_int_to_ext_idx = x_int + 1;
%3. Convolution for the interpolated data
conv_x = cat(3,extent_image(:,x_int+1), extent_image(:,x_int+2),...
extent_image(:,x_int+3), extent_image(:,x_int+4));
scaled_image_x = dot(X, conv_x, 3);
scaled_image_x(:,1) = input_image(:,1);
scaled_image_x(:,end) = input_image(:,end);
end
cubic_conv_x调用的cubic_kernel.m函数文件为:
function [ kernel_res ] = cubic_kernel( s )
kernel_res = zeros(size(s));
kernel_res(abs(s)<eps) = 1;
kernel_res(abs(s-1)<eps) = 0;
kernel_res(abs(s-2)<eps) = 0;
kernel_res((s>0 & s < 1)) = kernel_0_1(s(s>0 & s < 1));
kernel_res((s>1 & s < 2)) = kernel_1_2(s(s>1 & s < 2));
end
function [ kernel_res ] = kernel_0_1( s )
s2 = s.*s;
s3 = s2.*s;
kernel_res = 1.5*s3 - 2.5*s2 + 1;
end
function [ kernel_res ] = kernel_1_2( s )
s2 = s.*s;
s3 = s2.*s;
kernel_res = -0.5*s3 + 2.5*s2 - 4*s + 2;
end
本文主要比较 cubic convolution c u b i c c o n v o l u t i o n 和最近邻插值、双线性插值算法的精度、频谱响应以及计算效率。
精度
cubic convolution c u b i c c o n v o l u t i o n 能够完美重建二次多项式,而线性插值只能无误差重建一次多项式,最近邻插值只能重建常数图像。而增加插值的采样数据点,还能提高 cubic convolution c u b i c c o n v o l u t i o n 的精度到重建三次多项式(具体方法可以参考原文)。
频响
由于 cubic convolution c u b i c c o n v o l u t i o n 本质上是卷积过程,因此可以计算其频响曲线,从而分析其高频丢失以及走样情况。 cubic convolution c u b i c c o n v o l u t i o n 和最近邻插值、双线性插值算法的 kernel k e r n e l 如图1,频响曲线如图2。虚线为理想的频响曲线, nyquist n y q u i s t 频率以上的频响为0, nyquist n y q u i s t 频率以下的频响都为1,既能保持图像的锐度,又不发生走样。从图2可以发现,最近邻插值会在高频出现走样,线性插值在中低频部分相对有较大的频响损失。而 cubic convolution c u b i c c o n v o l u t i o n 的频响最接近理想响应曲线,其对图像的缩放最能保持图像原样,而不发生走样。
效率
最近邻插值、线性插值以及 cubic convolution c u b i c c o n v o l u t i o n 算法,其计算复杂度是越来越高的。但是 cubic convolution c u b i c c o n v o l u t i o n 在效果和计算效率上能做到比较好的平衡,而且其实现本质是卷积,利于硬件实现,所以能很好的进行加速,所以高档软件以及印刷常用 cubic convolution c u b i c c o n v o l u t i o n 算法。
由于 cubic convolution c u b i c c o n v o l u t i o n 本质上是卷积过程其中,虚线为理想的频响曲线, nyquist n y q u i s t 频率以上的频响为0, nyquist n y q u i s t 频率以下的频响都为1,即保持图像的锐度,又不发生走样。从图2可以发现,最近邻插值会在高频出现走样,线性插值在中低频部分相对有较大的频响损失。而 cubic convolution c u b i c c o n v o l u t i o n 的频响最接近理想响应曲线,其对图像的缩放最能保持图像原样,而不发生走样。
效率
最近邻插值、线性插值以及 cubic convolution c u b i c c o n v o l u t i o n 算法,其计算复杂度是越来越高的。但是 cubic convolution c u b i c c o n v o l u t i o n 在效果和计算效率上能做到比较好的平衡,而且其实现本质是卷积,利于硬件实现,所以能很好的进行加速,所以高档软件以及印刷常用 cubic convolution c u b i c c o n v o l u t i o n 算法。
对二维连续函数 f(x,y)=sin(0.5r2) f ( x , y ) = s i n ( 0.5 r 2 ) ,在区间 [0,xmax]∗[y,ymax] [ 0 , x m a x ] ∗ [ y , y m a x ] 上进行采样获得一张分辨率为 64∗64 64 ∗ 64 的小图 I0 I 0 ,其采样间隔为 (h0x,h0y) ( h 0 x , h 0 y ) 。然后在同样的函数区间 [0,xmax]∗[y,ymax] [ 0 , x m a x ] ∗ [ y , y m a x ] 上,用采样间隔为 (h1x,h1y) ( h 1 x , h 1 y ) 的方式,获得分辨率为 350∗336 350 ∗ 336 图像 Iorg I o r g 。
然后用 I0 I 0 ,分别通过最近邻、双线性和 cubic convolution c u b i c c o n v o l u t i o n 算法插值获得 Inearest I n e a r e s t 、 Ibilinear I b i l i n e a r 和 Icubic I c u b i c 。
1. CSDN资源:cubic convolution/bilinear/nearest image resize matlab
2. Github: cubic_convolution