数字图像处理(一)图像插值(Python)

数字图像在当代社会有着非常重要的作用,图像的插值作为一种基本的图像处理方法,在很多情况下可以很好的提高图像分辨率,提升图像观感。图像的插值方法主要有以下三种:

  • 最近邻插值
  • 双线性插值
  • 双三次插值

最近邻插值

最近邻插值,顾名思义,在插值时寻找距离图像像素点最近的像素点的值进行图像像素的填充。这种图像插值方法运算速度快,可以很快的出结果。缺点是插值效果较差,由于直接采用最近的像素点的像素值作为插值数据,因此导致在图像边缘,过渡等颜色变化较为明显的地方会出现较为严重的锯齿。 最近邻插值

实现代码如下

1
2
3
4
5
6
7
8
9
10
for i in range(2048):
for j in range(2048):
if i<=2044 and j<=2044:
result[i][j]=img[round(i/4)][round(j/4)][0]
else:
result[i][j]=img[math.floor(i/4)][math.floor(j/4)][0]
result=result.astype(np.uint8)
cv.namedWindow("test",cv.WINDOW_NORMAL)
cv.imshow("test",result)
cv.waitKey(0)

双线性插值

双线性插值采用线性的方法对图像进行插值,对于插值图像中的某个像素点,该点的像素值由距离其最近的四个像素值通过线性计算获得。插值得到的结果较好,计算量相比于最近邻要满,但远快于双三次插值,最终得到的插值图像结果除一些小细节之外和双三次插值得到的插值结果相当。可以用来快速,大量的插值图片。 双线性插值 实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for i in range(2048):
for j in range(2048):
if i<2044 and j<2044:
l=i//4
k=j//4
a=i/4-i//4
b=j/4-j//4
result[i][j]=img[l][k][0]*(1-a)*(1-b)+img[l+1][k][0]*a*(1-b)+img[l][k+1][0]*(1-a)*b+img[l+1][k+1][0]*a*b
else:
result[i][j]=img[i//4][j//4][0]
result=result.astype(np.uint8)
cv.namedWindow("test",cv.WINDOW_NORMAL)
cv.imshow("test",result)
cv.waitKey(0)

在图像边缘处采取最近邻插值

双三次插值

双三次插值采用非线性的计算方法,利用三次函数对于图像像素值进行计算。每个像素值由其周围的4*4即16个像素点的像素值计算获得。插值质量较高,运算速度较慢,Photoshop所用的插值方法就是双三次插值。 \[ f_3(x,y)=\sum_{i=0}^3\sum_{j=0}^3a_{ij}x_iy_i \]

实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def weight(x):
a=-0.5
x=abs(x)
if x<=1:
return (a+2)*x**3-(a+3)*x**2+1
if x<2:
return a*x**3-5*a*x**2+8*a*x-4*a
return 0

for i in range(2048):
for j in range(2048):
if i>4 and i<2040 and j>4 and j<2040:
for k in range(4):
for w in range(4):
result[i][j]+=img[i//4+k-1][j//4+w-1][0]*weight(i/4-(i//4+k-1))*weight(j/4-(j//4+w-1))
else:
result[i][j]=img[i//4][j//4][0]
result=result.astype(np.uint8)
cv.namedWindow("test",cv.WINDOW_NORMAL)
cv.imshow("test",result)
cv.waitKey(0)

结束语

这三种插值方法是图像插值的传统方法,分辨率的提升是基于局部像素的综合运算得到空白像素的像素值。这样的插值方法可以满足当代社会的绝大部分需求,但如果要追求更好的插值效果,或是将图像分辨率成几十倍的扩充即超分辨率,这样的插值方法就不能满足需求。这时,就需要通过一些其他的方法例如机器学习来进行图片质量的提升。