验证码识别的一些方法(未完成)

爬虫程序

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
29
30
31
32
33
34
35
36
37
38
39
40
41
# 爬取图片的爬虫
import requests
import time
import os
import uuid

'''
生成 uuid 作为文件名
'''
def generate_uuid():
return str(uuid.uuid4()).replace('-', '')

'''
生成请求验证码的 url
'''
def generate_url():
base_url = 'https://jxfw.gdut.edu.cn/yzm?d='
return base_url + str(round(time.time() * 1000))

def get_images():
url = generate_url()
try:
response = requests.get(url)
# 获取的文本实际上是图片的二进制文本
img = response.content
# 将他拷贝到本地文件 w 写 b 二进制 wb代表写入二进制文本
#保存路径
path= os.path.join('imgs/OriginalPicture/', generate_uuid() + '.jfif')
with open(path, 'wb') as f:
f.write(img)
except Exception as err:
print('请求出现异常!')
print('请求 url:{}'.format(url))
print(err)

if __name__ == '__main__':
i = 0;
while(i < 1000):
get_images()
time.sleep(0.02)
i+=1

图片示例:

图像预处理

灰度化

常用方法有分量法、加权平均法等,这里已经是灰度图片,所以不作处理。

分量法

分量法的主要思想便是取彩色图像三通道其中的任意一个通道分量,将它作为灰度图像的灰度值,按照现实应用选择一个通道。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>#encoding:utf-8
>import cv2
>import numpy as np
>import matplotlib.pyplot as plt

>#读取原始图像
>img = cv2.imread('miao.png')
>b = image[:, :, 0]
>g = image[:, :, 1]
>r = image[:, :, 2]
>#也可以直接用opencv的split函数
>#(b, g, r) = cv2.split(image)
>cv2.imshow("b", b)
>cv2.imshow("g", g)
>cv2.imshow("r", r)
>#等待显示
>cv2.waitKey(0)
>cv2.destroyAllWindows()

二值化

简单阈值法

如果像素值大于阈值,则为其分配一个值(可以是白色),否则分配另一个值(可以是黑色)。

使用的函数是cv2.threshold。 第一个参数是源图像,它应该是灰度图像。 第二个参数是用于对像素值进行分类的阈值。 第三个参数是maxVal,它表示像素值大于(有时小于)阈值时要给定的值。 OpenCV提供了不同的阈值样式,它由函数的第四个参数决定。 不同的类型是:

  • cv2.THRESH_BINARY
  • cv2.THRESH_BINARY_INV
  • cv2.THRESH_TRUNC
  • cv2.THRESH_TOZERO
  • cv2.THRESH_TOZERO_INV

Two outputs are obtained. First one is a retval which will be explained later. Second output is our thresholded image.

第四个参数决定的不同类型效果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('gradient.png',0)
ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)

titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

for i in xrange(6):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])

plt.show()

自适应阈值法

上面的方法使用全局值作为阈值。 但是,在图像在不同区域具有不同照明条件的所有条件下,可能并不总是一件好事。 在这种情况下,我们采用自适应阈值。 在这种情况下,算法会为图像的一小部分计算阈值。 因此,对于同一图像的不同区域,我们获得了不同的阈值,对于光照变化的图像,它可以提供更好的结果。

It has three ‘special’ input params and only one output argument.

  • Adaptive Method - It decides how thresholding value is calculated.

    cv2.ADAPTIVE_THRESH_MEAN_C : threshold value is the mean of neighbourhood area.cv2.ADAPTIVE_THRESH_GAUSSIAN_C : threshold value is the weighted sum of neighbourhood values where weights are a gaussian window.

  • Block Size - It decides the size of neighbourhood area.

  • C - It is just a constant which is subtracted from the mean or weighted mean calculated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('dave.jpg',0)
img = cv2.medianBlur(img,5)

ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)

titles = ['Original Image', 'Global Thresholding (v = 127)',
'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, th1, th2, th3]

for i in xrange(4):
plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()

otsus-binarization

在第一部分中,我告诉您有第二个参数retVal。 当我们进行OtsuBinarization时,就会使用它。 那是什么

在全局阈值化中,我们对阈值使用了任意值,对吧? 因此,我们如何知道我们选择的值是好还是不好? 答案是,反复试验的方法。 但是考虑双峰图像(简单地说,双峰图像是直方图具有两个峰值的图像)。 对于该图像,我们可以近似地将这些峰中间的值作为阈值,对吧? 这就是Otsu二值化所做的。 因此,简单来说,它会自动根据双峰图像的图像直方图计算阈值。 (对于非双峰图像,二值化将不准确。)

为此,使用了我们的cv2.threshold()函数,但传递了一个额外的标志cv2.THRESH_OTSU。 对于阈值,只需传递零即可。 然后,算法找到最佳阈值,并将您作为第二个输出retVal返回。 如果未使用Otsu阈值,则retVal与您使用的阈值相同。

看看下面的例子。 输入图像为噪点图像。 在第一种情况下,我将全局阈值设置为127。在第二种情况下,我直接应用了Otsu的阈值设置。 在第三种情况下,我使用5x5高斯核对图像进行了滤波以去除噪声,然后应用Otsu阈值处理。 了解噪声过滤如何改善结果。

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
29
30
31
32
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('noisy2.png',0)

# global thresholding
ret1,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)

# Otsu's thresholding
ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# Otsu's thresholding after Gaussian filtering
blur = cv2.GaussianBlur(img,(5,5),0)
ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# plot all the images and their histograms
images = [img, 0, th1,
img, 0, th2,
blur, 0, th3]
titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)',
'Original Noisy Image','Histogram',"Otsu's Thresholding",
'Gaussian filtered Image','Histogram',"Otsu's Thresholding"]

for i in xrange(3):
plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])
plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)
plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([])
plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray')
plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([])
plt.show()

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×