最近邻插值及Matlab实现
一、简单实例
采用简单实例进行对最近邻插值的介绍,假设现有
3
×
3
3\times3
3×3大小的灰度图
s
r
c
src
src,如下所示:
[
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
]
\left[\begin{array}{ccc} 0.1&0.2&0.3\\0.4&0.5&0.6\\0.7&0.8&0.9 \end{array}\right]
⎣⎡0.10.40.70.20.50.80.30.60.9⎦⎤目标图像
d
s
t
dst
dst期望大小为
5
×
5
5\times5
5×5,则若要构建原始图像与目标图像之间的对应关系,明显可得到下述表达式:
{
s
r
c
X
=
d
s
t
X
×
(
s
r
c
W
i
d
t
h
/
d
s
t
W
i
d
t
h
)
s
r
c
Y
=
d
s
t
Y
×
(
s
r
c
H
e
i
g
h
t
/
d
s
t
H
e
i
g
h
t
)
\left\{\begin{array}{l} srcX=dstX\times(srcWidth/dstWidth) \\ srcY=dstY\times(srcHeight/dstHeight) \end{array}\right.
{srcX=dstX×(srcWidth/dstWidth)srcY=dstY×(srcHeight/dstHeight)其中
s
r
c
X
srcX
srcX、
s
r
c
Y
srcY
srcY分别为目标图像
d
s
t
X
dstX
dstX、
d
s
t
Y
dstY
dstY处所对应的原图像坐标,那么,假设现需要求解目标图像的第一个像素,则有:
{
s
r
c
X
=
1
×
(
3
/
5
)
=
0.6
s
r
c
Y
=
1
×
(
3
/
5
)
=
0.6
\left\{\begin{array}{l} srcX=1\times(3/5)=0.6 \\ srcY=1\times(3/5)=0.6 \end{array}\right.
{srcX=1×(3/5)=0.6srcY=1×(3/5)=0.6则根据最近邻原则,对所求数值采用四舍五入,得到对应原图像坐标为:
(
1
,
1
)
(1,1)
(1,1),即目标图像的第一个像素对应原始图像的第一个像素,为0.1。全部求解完毕得到目标图像如下:
[
0.1
0.1
0.2
0.2
0.3
0.1
0.1
0.2
0.2
0.3
0.4
0.4
0.5
0.5
0.6
0.4
0.4
0.5
0.5
0.6
0.7
0.7
0.8
0.8
0.9
]
\left[\begin{array}{ccccc} 0.1&0.1&0.2&0.2&0.3\\ 0.1&0.1&0.2&0.2&0.3\\ 0.4&0.4&0.5&0.5&0.6\\ 0.4&0.4&0.5&0.5&0.6\\ 0.7&0.7&0.8&0.8&0.9 \end{array}\right]
⎣⎢⎢⎢⎢⎡0.10.10.40.40.70.10.10.40.40.70.20.20.50.50.80.20.20.50.50.80.30.30.60.60.9⎦⎥⎥⎥⎥⎤ 通过上述简单例子可以看出,最近邻插值是十分粗糙简单的,仅仅对目标图像对应原始图像的位置进行了考虑,所得到的目标图像中的数值全在原始图像中取得,即会出现目标图像中的方块区域内的数值一致。若采用最近邻插值对图像进行放大,那么便会出现大量的马赛克。
事实上,对于上述原始图像与目标图像之间的映射公式,常使用修正后的公式,如下:
{
s
r
c
X
=
(
d
s
t
X
+
0.5
)
×
(
s
r
c
W
i
d
t
h
/
d
s
t
W
i
d
t
h
)
−
0.5
s
r
c
Y
=
(
d
s
t
Y
+
0.5
)
×
(
s
r
c
H
e
i
g
h
t
/
d
s
t
H
e
i
g
h
t
)
−
0.5
\left\{\begin{array}{l} srcX=(dstX+0.5)\times(srcWidth/dstWidth) - 0.5 \\ srcY=(dstY+0.5)\times(srcHeight/dstHeight)-0.5 \end{array}\right.
{srcX=(dstX+0.5)×(srcWidth/dstWidth)−0.5srcY=(dstY+0.5)×(srcHeight/dstHeight)−0.5修正后的公式可以保证原始图像与目标图像的中心位置处是同一个数值,这一点通过简单验算便可证明,此处不进行证明,后续对于双线性插值、双三次插值等插值方法的使用亦采用此公式。如下图所示为利用最近邻插值实现图像放大三倍的结果。
二、Matlab实现
由于Matlab进行运算时,下标由1开始,那么根据上述目标图像与原始图像的映射公式可知,因为存在向最近整数取整操作,难免会出现目标图像所对应的原始图像坐标为0或超出图像大小。对于这种情况,常使用扩展边界或对称边界两种方法,其中对称边界的方法实现效果更好,因此此处Matlab实现采用的对称边界扩展图像,Matlab实现如下:
function R = nearest(src, scale)
%% 最近邻插值
src = double(src) / 255;
% 判断是灰度图还是RGB图像
if ismatrix(src)
R = zeros(floor(size(src) * scale));
else
R = zeros([floor(size(src, 1, 2) * scale), 3]);
end
% 扩展原始图像
misrc = zeros([size(src, 1, 2) + 2 * floor(scale), size(R, 3)]);
for i = 1 : size(R, 3)
tmp = padarray(src(:, :, i), [floor(scale), floor(scale)], 'symmetric');
misrc(:, :, i) = tmp;
end
for i = 1 : size(R, 1)
for j = 1 : size(R, 2)
srcX = round((i + 0.5) / scale - 0.5);
srcY = round((j + 0.5) / scale - 0.5);
tmp = misrc(floor(srcX + scale), floor(srcY + scale), :);
R(i, j, :) = tmp(:);
end
end
end