Programming Assignment 1
Write a function “imresize” that gets the original image, original size, and target size as input and returns the output image at the target size using bilinear interpolation. Apply the imresize to one of the test images (256x256) to scale them to 1.5 and 0.75 (384x384 and 192x192 respectively).
提交报告内容包括实现原理,程序输入与输出图像对比,结果分析,及代码。编程语言不限。
实现原理:
首先,图中有5个像素点:
Q
00
,
Q
01
,
Q
10
,
Q
11
Q_{00},Q_{01},Q_{10},Q_{11}
Q 0 0 , Q 0 1 , Q 1 0 , Q 1 1 ,
P
P
P 。其中四个红色点
Q
Q
Q 是原图的点,绿色点
P
P
P 是目标图的像素点在原图上的投影!四个红色点
Q
Q
Q 就是投影点
P
P
P 的四周最近的点。通过四个红色点
Q
Q
Q ,可以计算出投影点
P
P
P 的像素值,这样目标图上的像素点的像素值也就得到了。
已知: 四个红色点
Q
Q
Q 的坐标值:
h
0
,
h
1
,
w
0
,
w
1
h_0,h_1,w_0,w_1
h 0 , h 1 , w 0 , w 1 四个红色点
Q
Q
Q 的像素值:
f
(
Q
00
)
,
f
(
Q
01
)
,
f
(
Q
10
)
,
f
(
Q
11
)
f(Q_{00}),f(Q_{01}),f(Q_{10}),f(Q_{11})
f ( Q 0 0 ) , f ( Q 0 1 ) , f ( Q 1 0 ) , f ( Q 1 1 ) 投影点
P
P
P 的坐标值:
h
,
w
h,w
h , w
目标图的点如何投影到原图上?
已知:
输入图的高和宽:height
s
r
c
,
_{s r c},
s r c , width
s
r
c
_{s r c}
s r c
目标图的高和宽:height
dst
,
_{\text {dst}},
dst , width
dst
_{\text {dst}}
dst
投影的公式是:
h
=
h
d
s
t
∗
∂
g
(
x
)
h=h_{d s t} * \partial g(x)
h = h d s t ∗ ∂ g ( x ) height
s
r
c
_{s r c}
s r c height
d
s
t
_{d s t}
d s t
w
=
w
d
s
t
∗
w
i
d
t
h
s
r
c
w
i
d
t
h
d
s
t
w=w_{d s t} * \frac{w i d t h_{s r c}}{w i d t h_{d s t}}
w = w d s t ∗ w i d t h d s t w i d t h s r c
但是这个公式有一个问题,可能会导致目标图的中心跟原图的中心不对齐。例如:原图是3x3,中心点坐标(1, 1);目标图是9x9,中心点坐标(4, 4);通过上面的公式计算,目标图中心点在原图的投影坐标:
h
=
4
∗
3
/
9
=
1.3333
≠
1
h=4 * 3 / 9=1.3333 \neq 1
h = 4 ∗ 3 / 9 = 1 . 3 3 3 3 = 1 。之所以会出现中心点不对齐,原因是每个像素点实际上是一个边长为1的正方形,所以对于坐标为
(
h
,
w
)
(h, w)
( h , w ) ,的像素点,它的中心其实是
(
h
+
0.5
,
w
+
0.5
)
(h+0.5, w+0.5)
( h + 0 . 5 , w + 0 . 5 ) 。所以精确计算应该是:
h
+
0.5
height
src
=
h
dst
+
0.5
height
dst
\frac{h+0.5}{\text {height}_{\text {src}}}=\frac{h_{\text {dst}}+0.5}{\text {height}_{\text {dst}}}
height src h + 0 . 5 = height dst h dst + 0 . 5
∂
g
(
x
)
w
+
0.5
w
i
d
t
h
s
r
c
=
∂
g
(
x
)
w
d
s
t
+
0.5
w
i
d
t
h
d
s
t
\partial g(x) w+0.5 w i d t h_{s r c}=\partial g(x) w_{d s t}+0.5 w i d t h_{d s t}
∂ g ( x ) w + 0 . 5 w i d t h s r c = ∂ g ( x ) w d s t + 0 . 5 w i d t h d s t
转换一下得到正确的投影公式:
h
=
(
h
d
s
t
+
0.5
)
∗
h
e
i
g
h
t
s
r
c
h
e
i
g
h
t
d
s
t
−
0.5
h=\left(h_{d s t}+0.5\right) * \frac{h e i g h t_{s r c}}{h e i g h t_{d s t}}-0.5
h = ( h d s t + 0 . 5 ) ∗ h e i g h t d s t h e i g h t s r c − 0 . 5
w
=
(
w
d
s
t
+
0.5
)
∗
w
i
d
t
h
s
r
c
w
i
d
t
h
d
s
t
−
0.5
w=\left(w_{d s t}+0.5\right) * \frac{w i d t h_{s r c}}{w i d t h_{d s t}}-0.5
w = ( w d s t + 0 . 5 ) ∗ w i d t h d s t w i d t h s r c − 0 . 5
如何插值计算得到投影点的像素值?
已知: 四个红色点
Q
Q
Q 的坐标值:
h
0
,
h
1
,
w
0
,
w
1
h_0,h_1,w_0,w_1
h 0 , h 1 , w 0 , w 1 四个红色点
Q
Q
Q 的像素值:
f
(
Q
00
)
,
f
(
Q
01
)
,
f
(
Q
10
)
,
f
(
Q
11
)
f(Q_{00}),f(Q_{01}),f(Q_{10}),f(Q_{11})
f ( Q 0 0 ) , f ( Q 0 1 ) , f ( Q 1 0 ) , f ( Q 1 1 ) 投影点
P
P
P 的坐标值:
h
,
w
h,w
h , w 思路是:每个
Q
Q
Q 点的像素值乘以各自的权重,然后相加得到投影点
P
P
P 像素值。
Q
Q
Q 点跟
P
P
P 点的距离越近,它的权重就越大。 双线性插值给出的算法很是简单粗暴:先在横轴方向上进行两次线性插值计算,然后在纵轴方向上进行一次插值计算。结合最开始那个图例看,就是先求
R
0
R_0
R 0 和
R
1
R_1
R 1 这两个蓝色点的像素值,然后再通过这两个值,求得点
P
P
P 的像素值。
具体计算如下:
f
(
R
0
)
≈
w
1
−
w
w
1
−
w
0
f
(
Q
00
)
+
w
−
w
0
w
1
−
w
0
f
(
Q
01
)
f\left(R_{0}\right) \approx \frac{w_{1}-w}{w_{1}-w_{0}} f\left(Q_{00}\right)+\frac{w-w_{0}}{w_{1}-w_{0}} f\left(Q_{01}\right)
f ( R 0 ) ≈ w 1 − w 0 w 1 − w f ( Q 0 0 ) + w 1 − w 0 w − w 0 f ( Q 0 1 )
f
(
R
1
)
≈
w
1
−
w
w
1
−
w
0
f
(
Q
10
)
+
w
−
w
0
w
1
−
w
0
f
(
Q
11
)
f\left(R_{1}\right) \approx \frac{w_{1}-w}{w_{1}-w_{0}} f\left(Q_{10}\right)+\frac{w-w_{0}}{w_{1}-w_{0}} f\left(Q_{11}\right)
f ( R 1 ) ≈ w 1 − w 0 w 1 − w f ( Q 1 0 ) + w 1 − w 0 w − w 0 f ( Q 1 1 )
f
(
P
)
≈
h
1
−
h
h
1
−
h
0
f
(
R
0
)
+
h
−
h
0
h
1
−
h
0
f
(
R
1
)
f(P) \approx \frac{h_{1}-h}{h_{1}-h_{0}} f\left(R_{0}\right)+\frac{h-h_{0}}{h_{1}-h_{0}} f\left(R_{1}\right)
f ( P ) ≈ h 1 − h 0 h 1 − h f ( R 0 ) + h 1 − h 0 h − h 0 f ( R 1 )
≈
h
1
−
h
h
1
−
h
0
(
w
1
−
w
w
1
−
w
0
f
(
Q
00
)
+
w
−
w
0
w
1
−
w
0
f
(
Q
01
)
)
+
h
−
h
0
h
1
−
h
0
(
w
1
−
w
w
1
−
w
0
f
(
Q
10
)
+
w
−
w
0
w
1
−
w
0
f
(
Q
11
)
)
\approx \frac{h_{1}-h}{h_{1}-h_{0}}\left(\frac{w_{1}-w}{w_{1}-w_{0}} f\left(Q_{00}\right)+\frac{w-w_{0}}{w_{1}-w_{0}} f\left(Q_{01}\right)\right)+\frac{h-h_{0}}{h_{1}-h_{0}}\left(\frac{w_{1}-w}{w_{1}-w_{0}} f\left(Q_{10}\right)+\frac{w-w_{0}}{w_{1}-w_{0}} f\left(Q_{11}\right)\right)
≈ h 1 − h 0 h 1 − h ( w 1 − w 0 w 1 − w f ( Q 0 0 ) + w 1 − w 0 w − w 0 f ( Q 0 1 ) ) + h 1 − h 0 h − h 0 ( w 1 − w 0 w 1 − w f ( Q 1 0 ) + w 1 − w 0 w − w 0 f ( Q 1 1 ) )
=
1
(
w
1
−
w
0
)
(
h
1
−
h
0
)
(
(
h
1
−
h
)
(
w
1
−
w
)
f
(
Q
00
)
+
(
h
1
−
h
)
(
w
−
w
0
)
f
(
Q
01
)
+
(
h
−
h
0
)
(
w
1
−
w
)
f
(
Q
10
)
+
(
h
−
h
0
)
(
w
−
w
0
)
f
(
Q
11
)
)
=\frac{1}{\left(w_{1}-w_{0}\right)\left(h_{1}-h_{0}\right)}\left(\left(h_{1}-h\right)\left(w_{1}-w\right) f\left(Q_{00}\right)+\left(h_{1}-h\right)\left(w-w_{0}\right) f\left(Q_{01}\right)+\left(h-h_{0}\right)\left(w_{1}-w\right) f\left(Q_{10}\right)+\left(h-h_{0}\right)\left(w-w_{0}\right) f\left(Q_{11}\right)\right)
= ( w 1 − w 0 ) ( h 1 − h 0 ) 1 ( ( h 1 − h ) ( w 1 − w ) f ( Q 0 0 ) + ( h 1 − h ) ( w − w 0 ) f ( Q 0 1 ) + ( h − h 0 ) ( w 1 − w ) f ( Q 1 0 ) + ( h − h 0 ) ( w − w 0 ) f ( Q 1 1 ) )
前面说了4个红色点
Q
Q
Q 是投影点
P
P
P 四周最近的点,显然4个红色点彼此间的距离都是1,也即
w
1
−
w
0
=
1
,
h
1
−
h
0
=
1
w_1-w_0=1,h_1-h_0=1
w 1 − w 0 = 1 , h 1 − h 0 = 1 。因此上式可写成
f
(
P
)
≈
(
h
1
−
h
)
(
w
1
−
w
)
f
(
Q
00
)
+
(
h
1
−
h
)
(
w
−
w
0
)
f
(
Q
01
)
+
(
h
−
h
0
)
(
w
1
−
w
)
f
(
Q
10
)
+
(
h
−
h
0
)
(
w
−
w
0
)
f
(
Q
11
)
f(P) \approx\left(h_{1}-h\right)\left(w_{1}-w\right) f\left(Q_{00}\right)+\left(h_{1}-h\right)\left(w-w_{0}\right) f\left(Q_{01}\right)+\left(h-h_{0}\right)\left(w_{1}-w\right) f\left(Q_{10}\right)+\left(h-h_{0}\right)\left(w-w_{0}\right) f\left(Q_{11}\right)
f ( P ) ≈ ( h 1 − h ) ( w 1 − w ) f ( Q 0 0 ) + ( h 1 − h ) ( w − w 0 ) f ( Q 0 1 ) + ( h − h 0 ) ( w 1 − w ) f ( Q 1 0 ) + ( h − h 0 ) ( w − w 0 ) f ( Q 1 1 ) 再令
u
=
h
−
h
0
,
v
=
w
−
w
0
u=h-h_0,v=w-w_0
u = h − h 0 , v = w − w 0 式子可进一步写成:
f
(
P
)
≈
f
(
Q
00
)
(
1
−
u
)
(
1
−
v
)
+
f
(
Q
01
)
(
1
−
u
)
v
+
f
(
Q
10
)
u
(
1
−
v
)
+
f
(
Q
11
)
u
v
f(P) \approx f\left(Q_{00}\right)(1-u)(1-v)+f\left(Q_{01}\right)(1-u) v+f\left(Q_{10}\right) u(1-v)+f\left(Q_{11}\right) u v
f ( P ) ≈ f ( Q 0 0 ) ( 1 − u ) ( 1 − v ) + f ( Q 0 1 ) ( 1 − u ) v + f ( Q 1 0 ) u ( 1 − v ) + f ( Q 1 1 ) u v
具体编程实现步骤
放大后图像的座标
(
x
′
,
y
′
)
(x',y')
( x ′ , y ′ ) 除以放大率
a
a
a ,可以得到对应原图像的座标
(
⌊
x
′
a
⌋
,
⌊
y
′
a
⌋
)
(\lfloor \frac{x'}{a}\rfloor , \lfloor \frac{y'}{a}\rfloor)
( ⌊ a x ′ ⌋ , ⌊ a y ′ ⌋ ) 。
求原图像的座标
(
⌊
x
′
a
⌋
,
⌊
y
′
a
⌋
)
(\lfloor \frac{x'}{a}\rfloor , \lfloor \frac{y'}{a}\rfloor)
( ⌊ a x ′ ⌋ , ⌊ a y ′ ⌋ ) 周围
4
4
4 邻域的座标
I
(
x
,
y
)
I(x,y)
I ( x , y ) ,
I
(
x
+
1
,
y
)
I(x+1,y)
I ( x + 1 , y ) ,
I
(
x
,
y
+
1
)
I(x,y+1)
I ( x , y + 1 ) ,
I
(
x
+
1
,
y
+
1
)
I(x+1, y+1)
I ( x + 1 , y + 1 ) :
分别求这4个点与
(
x
′
a
,
y
′
a
)
(\frac{x'}{a}, \frac{y'}{a})
( a x ′ , a y ′ ) 的距离,根据距离设置权重:
w
=
d
∑
d
w = \frac{d}{\sum\ d}
w = ∑ d d
根据下式求得放大后图像
(
x
′
,
y
′
)
(x',y')
( x ′ , y ′ ) 处的像素值:
d
x
=
x
′
a
−
x
d
y
=
y
′
a
−
y
I
′
(
x
′
,
y
′
)
=
(
1
−
d
x
)
(
1
−
d
y
)
I
(
x
,
y
)
+
d
x
(
1
−
d
y
)
I
(
x
+
1
,
y
)
+
(
1
−
d
x
)
d
y
I
(
x
,
y
+
1
)
+
d
x
d
y
I
(
x
+
1
,
y
+
1
)
d_x = \frac{x'}{a} - x\\ d_y = \frac{y'}{a} - y\\ I'(x',y') = (1-d_x)\ (1-d_y)\ I(x,y) + d_x\ (1-d_y)\ I(x+1,y) + (1-d_x)\ d_y\ I(x,y+1) + d_x\ d_y\ I(x+1,y+1)
d x = a x ′ − x d y = a y ′ − y I ′ ( x ′ , y ′ ) = ( 1 − d x ) ( 1 − d y ) I ( x , y ) + d x ( 1 − d y ) I ( x + 1 , y ) + ( 1 − d x ) d y I ( x , y + 1 ) + d x d y I ( x + 1 , y + 1 )
输入与输出图像对比
输出(0.75倍)
输入原始图像
输出(1.5倍)
输出(0.75倍)
输入原始图像
输出(1.5倍)
代码
"""
AUTHOR: Tian YJ
CREATE: 2020-03-15
FUNCTION: Bi-Linear interpolation
"""
import cv2
import numpy as np
def imresize ( img, shape_s, shape_d) :
print ( "原始图片大小:" , shape_s)
print ( "目标图片大小:" , shape_d)
H_s, W_s = shape_s
H_d, W_d = shape_d
y = np. arange( H_d) . repeat( W_d) . reshape( W_d, - 1 )
x = y. T
y = ( ( y+ 0.5 ) / ( H_d / H_s) ) - 0.5
x = ( ( x+ 0.5 ) / ( W_d / W_s) ) - 0.5
x_int = np. floor( x) . astype( np. int )
y_int = np. floor( y) . astype( np. int )
x_int = np. minimum( x_int, W_s- 2 )
y_int = np. minimum( y_int, H_s- 2 )
dx = x - x_int
dy = y - y_int
dx = np. repeat( np. expand_dims( dx, axis= - 1 ) , 3 , axis= - 1 )
dy = np. repeat( np. expand_dims( dy, axis= - 1 ) , 3 , axis= - 1 )
out = ( 1 - dx) * ( 1 - dy) * img[ y_int, x_int] + dx * ( 1 - dy) * img[ y_int, x_int+ 1 ] + (
1 - dx) * dy * img[ y_int+ 1 , x_int] + dx * dy * img[ y_int + 1 , x_int+ 1 ]
out = out. astype( np. uint8)
return out
if __name__ == '__main__' :
ratio = str ( input ( "请输入需要放大的倍数:" ) )
path_work = 'C:/Users/86187/Desktop/image_result/'
img_name = 'CARTOON'
file_in = path_work + str ( img_name) + '.jpg'
file_out = path_work + str ( img_name) + '_resize_' + ratio + '.jpg'
img = cv2. imread( file_in) . astype( np. float )
ratio = float ( ratio)
shape_s = ( img. shape[ 0 ] , img. shape[ 1 ] )
shape_d = ( int ( ratio* shape_s[ 0 ] ) , int ( ratio* shape_s[ 1 ] ) )
out = imresize( img, shape_s, shape_d)
cv2. imshow( "result" , out)
cv2. waitKey( 0 )
cv2. destroyAllWindows( )
cv2. imwrite( file_out, out)