通过图像像素值对图像进行降噪处理

如何更好获取图像的像素值

对于一张彩色的验证码,肯定少不了RBG三通道或者是RGBA四通道,其中在四通道的图像中,是在原来的基础上加上了alpha通道,即透明度。

彩色的图像虽然人为可以更好的区分,但是对于机器而言,并不能去区分。因此如何让机器进行区分这就是接下来要说明的问题。

首先,对于人而言,彩色的图像有时候是很容易区分出来的,对于机器而言,灰色或者黑白的图像才是机器容易识别的。因此,对于有颜色上区别的验证码而言,可以使用像素值过滤的方式进行降噪。当然,该方法只能解决部分,并不是通用的方法。

在开始接下来的内容之前需要先明白灰度值的计算公式:Gray = R*0.299 + G*0.587 + B*0.114,该公式为一个心理公式。

之后对于黑白图像,在图像中0表示黑色,255表示白色。

图像降噪处理之图像灰度化转换

以下代码均运行在jupyter notebook中。

开篇来张图:

1
2
3
4
5
6
7
8
9
10
import matplotlib.pyplot as plt
import glob
import numpy as np

filenames = glob.glob('images/*.jpeg')

filename = filenames[0]
img = plt.imread(filename)

plt.imshow(img)

对于给出的这张图片可以很明显的看出,可以根据不同的颜色进行图像降噪、去干绕线。

首先需要将彩色图片转为灰色图片,这样才能保证多通道的数据图像变成单通道的数据图像。

1
2
3
4
5
6
def rgb2gray(img):
return np.dot(img[...,:3], [0.299, 0.587, 0.114])

gray = rgb2gray(img)

plt.imshow(gray, cmap = plt.get_cmap('gray'))

在将图像转化为灰度图像之后,就可以很明显的看出,图像的像素值由原来的三通道变成了单通道数据。

图像降噪处理之灰度图像像素值平均值

平均值,是反应一组数据的最好表现。在图像像素值中,通过平均值进行过滤可以达到意想不到的效果。

如果一张图片中有很多无关紧要的干扰因素,如空白区域,可以考虑将图像的像素值进行设定到一定的范围中,这样就是这些验证码的平均像素值了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def avg_image(image, w, h):
points = []
for i in range(w):
for j in range(h):
if image[i, j] < 180:
points.append(image[i, j])

avg_point = sum(points) // len(points)
return avg_point

w,h = gray.shape

avg_point = avg_image(gray, w, h)

import copy

cgray = copy.copy(gray)

图像降噪处理之像素值的增强与削弱

在此处我们规定,图像的削弱点为平均值的像素值,这样可以保证对深颜色的再次加深,浅色的再次削弱。

1
2
3
4
5
6
7
for i in range(w):
for j in range(h):
r = gray[i, j] - avg_point
if r < 1:
cgray[i, j] = 0
elif r > 0:
cgray[i, j] = 255

在经过上述处理后,效果就变为

图像降噪处理之8邻域、4邻域降噪

8邻域降噪 的前提是将图片灰度化,即将彩色图像转化为灰度图像。以RGN色彩空间为例,彩色图像中每个像素的颜色由R 、G、B三个分量决定,每个分量由0到255种取值,这个一个像素点可以有一千多万种颜色变化。而灰度则是将三个分量转化成一个,使每个像素点只有0-255种取值,这样可以使后续的图像计算量变得少一些。

图片越接近白色的点像素越接近255,越接近黑色的点像素越接近0,而且验证码字符肯定是非白色的。对于其中噪点大部分都是孤立的小点的,而且字符都是串联在一起的。8邻域降噪 的原理就是依次遍历图中所有非白色的点,计算其周围8个点中属于非白色点的个数,如果数量小于一个固定值,那么这个点就是噪点。对于不同类型的验证码这个阈值是不同的,所以可以在程序中配置,不断尝试找到最佳的阈值 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def depoint(img, k):
pixdata = img
w, h = img.shape
for y in range(1, h-1):
for x in range(1, w-1):
count = 0
if pixdata[x, y - 1] > 254:
count += 1
if pixdata[x, y + 1] > 254:
count += 1
if pixdata[x - 1, y] > 254:
count += 1
if pixdata[x + 1, y] > 254:
count += 1
if pixdata[x - 1, y - 1] > 254:
count += 1
if pixdata[x - 1, y + 1] > 254:
count += 1
if pixdata[x + 1, y - 1] > 254:
count += 1
if pixdata[x + 1, y + 1] > 254:
count += 1
if count > k:
pixdata[x, y] = 255
return pixdata

np_img = depoint(cgray, 8)
np_img = depoint(np_img, 4)

效果如下:

虽然看起来效果和经过像素值削弱过的图像没有两样,这是因为,在图像经过像素值调整的时候直接将图像的像素值做了调整,如果将两者顺序进行调整,将会看到不同效果。

图像降噪处理之pycapt库的使用

之所以引用这个库,是因为在降噪的过程中,以上的方法会降噪不是很好,如上图,可以看出仍旧有两条干扰线,使用pycapt库是为了将剩余的噪音处理掉。

1
2
3
4
5
6
7
8
9
import pycapt
img = Image.fromarray(np_img.astype('uint8'))
img = pycapt.dele_line(img, 2)
img = pycapt.dele_noise(img, N=2, Z=1)
img = pycapt.tran_90(img)
img = pycapt.dele_line(img, 2)
img = pycapt.dele_noise(img, N=2, Z=1)
img = pycapt.tran_90(img)
img.show()

效果如下:

处理前的效果:

总结

图像降噪处理有很多的方法,此处只是使用了一种大众化的方法,该方法可以解决很多有色值差的图像,但是,效果并不是很好。所以想要好的降噪后的图像,需要不断的寻找更好的方法。