1 算法原理
提出此算法的背景是基于图片的缩放,在图片缩放的过程中,实质上就是将原图像像素矩阵像素值,填到目标图像像素矩阵中,目标图像像素矩阵可能比原图像像素矩阵大(图片放大),也可能小(图片缩小)。我们假设图片的宽(
W
i
d
t
h
Width
Width)和高(
H
e
i
g
h
t
Height
Height)是按同比例缩放的,那么
s
r
c
X
s
r
c
W
i
d
t
h
=
d
s
t
X
d
s
t
W
i
d
t
h
\frac{srcX}{srcWidth}= \frac{dstX}{dstWidth}
srcWidthsrcX=dstWidthdstX
s
r
c
Y
s
r
c
H
e
i
g
h
t
=
d
s
t
Y
d
s
t
H
e
i
g
h
t
\frac{srcY}{srcHeight}=\frac{dstY}{dstHeight}
srcHeightsrcY=dstHeightdstY
也就是,给定一个目标图片矩阵在(
d
s
t
X
dstX
dstX,
d
s
t
Y
dstY
dstY)处的坐标,计算出对应缩放前原图像的某点坐标(
s
r
c
X
srcX
srcX,
s
r
c
Y
srcY
srcY),将后者的像素RGB值填入前者。但在计算中常常遇到算出的(
s
r
c
X
srcX
srcX,
s
r
c
Y
srcY
srcY)为浮点型的情况,如图1。而在像素坐标中,所有的坐标都应该为整型,因此本文的这两个算法就是为了解决浮点型原图像坐标的处理问题。
1.1 最近邻插值
算法思路就是将浮点型坐标用int()强制转换为整型,在图2中,浮点型像素点P的坐标被强制转换成整型后,就转为A点,也即用A点单个点的像素代表目标图像矩阵中某个像素值,算法的优点在于速度快,但从图2中就可以看出此算法的误差很大,容易造成图像缩放失真。
1.2 双线性插值算法
算法思路是用浮点型像素点P周围相邻的四个像素,如图2中的A、B、C、D四个点像素的加权平均值来表征P的像素。具体的做法是用横轴、纵轴的距离来表示权重,例如:
△
x
P
,
A
△x_{P,A}
△xP,A=
u
u
u,
△
y
P
,
A
△y_{P,A}
△yP,A=
v
v
v。若用f(M)表示M点的像素值,则P点像素中的A像素分量就为
(
1
−
u
)
(
1
−
v
)
f
(
A
)
(1-u)(1-v)f(A)
(1−u)(1−v)f(A)
显然,u、v越大,P点离A点的距离就越远;那么(1-u)(1-v)就越小,从而A像素f(A)的权重就越小。根据这个思路,可以写出:
f
(
M
)
=
(
1
−
u
)
(
1
−
v
)
f
(
A
)
+
u
(
1
−
v
)
f
(
B
)
+
(
1
−
u
)
v
f
(
C
)
+
u
v
f
(
D
)
f(M)=(1-u)(1-v)f(A)+u(1-v)f(B)+(1-u)vf(C)+uvf(D)
f(M)=(1−u)(1−v)f(A)+u(1−v)f(B)+(1−u)vf(C)+uvf(D)
现在要考虑一个目标图像像素坐标得出过程的问题,正如开头所列写的:
s
r
c
X
=
s
r
c
W
i
d
t
h
d
s
t
X
d
s
t
W
i
d
t
h
srcX=srcWidth\frac {dstX}{dstWidth}
srcX=srcWidthdstWidthdstX
s
r
c
Y
=
s
r
c
H
e
i
g
h
t
d
s
t
Y
d
s
t
H
e
i
g
h
t
srcY=srcHeight\frac{dstY}{dstHeight}
srcY=srcHeightdstHeightdstY
如果直接利用这个相似公式,得出的目标图像相对于原图像将不是中心化的,为了说明这一点,假设现在希望将一个5×5的图像缩小为3×3的图像,直接相似关系得出的结果为图3(i)所示,即最右侧和最下侧的像素其实没有参与运算,我们希望得到的图像是如图3(ii)的,这样的放缩才能更多地体现原图像的信息,因此我们需要对放缩公式进行一个补偿修正。
考虑将一个m×m的像素矩阵放缩为M×M的像素矩阵,原像素矩阵的中心为(
(
m
−
1
)
2
\frac{(m-1)}{2}
2(m−1),
(
m
−
1
)
2
\frac{(m-1)}{2}
2(m−1)),例如一个5×5矩阵,其中心就为(2,2),若为偶数阶矩阵,其中心可理解为一个虚拟的浮点数像素。将目标像素矩阵的中心(
(
M
−
1
)
2
\frac{(M-1)}{2}
2(M−1),
(
M
−
1
)
2
\frac{(M-1)}{2}
2(M−1))代入相似公式,得到(仅列出横坐标,纵坐标同理):
s
r
c
X
=
(
M
−
1
)
2
m
M
srcX=\frac{(M-1)}{2}\frac{m}{M}
srcX=2(M−1)Mm
设置一个误差量:
b
i
a
s
=
s
r
c
X
−
(
m
−
1
)
2
bias=srcX-\frac{(m-1)}{2}
bias=srcX−2(m−1)
化简即得:
b
i
a
s
=
1
2
(
1
−
m
M
)
bias=\frac{1}{2}(1-\frac{m}{M})
bias=21(1−Mm)
因此对相似公式进行修正,得到:
s
r
c
X
=
d
s
t
X
s
r
c
W
i
d
t
h
d
s
t
W
i
d
t
h
−
b
i
a
s
srcX=dstX\frac{srcWidth}{dstWidth}-bias
srcX=dstXdstWidthsrcWidth−bias
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
−
b
i
a
s
srcY=dstY\frac{srcHeight}{dstHeight}-bias
srcY=dstYdstHeightsrcHeight−bias
这就是中心化公式的由来
2 源码实现
这里仅贴出双线性插值算法的核心代码段:
for i in range(dstHeight):
for j in range(dstWidth):
srcX = j*(srcWidth/dstWidth)-bias_Width
srcY = i*(srcHeight/dstHeight)-bias_Height
srcX_0 = int(np.floor(srcX))
u = np.float(srcX-srcX_0)
srcX_1 = int(np.ceil(srcX))
if srcX_1>srcWidth-1: #消除数组越界问题
srcX_1 = srcX_1-1
srcY_0 = int(np.floor(srcY))
v = srcY-srcY_0
srcY_1 = int(np.ceil(srcY))
if srcY_1>srcHeight-1:
srcY_1 = srcY_1-1
dstImgInfo[i][j] =(1-u)*(1-v)*img[srcY_0][srcX_0]+u*(1-v)*img[srcY_0][srcX_1]+(1-u)*v*img[srcY_1][srcX_0]+u*v*img[srcY_1][srcX_1]
🚀 计算机视觉基础教程说明
章号 内容
0 色彩空间与数字成像
1 计算机几何基础
2 图像增强、滤波、金字塔
3 图像特征提取
4 图像特征描述
5 图像特征匹配
6 立体视觉
7 项目实战
🔥 更多精彩专栏: