本文介绍了使用Pillow与Tesseract识别验证码的例子。
本文介绍的方法只适用于文字比较工整且与背景/噪点颜色色差明显的验证码。
我们以泉州市政府采购网为例

目标验证码

加载验证码图片

使用reqeusts请求验证码,并用pillow加载图片

1
2
3
4
5
6
7
8
import requests
from PIL import Image
from io import BytesIO

resp = requests.get('http://zfcg.fjqz.gov.cn/ucapqzzfcg/portal/validate/img2.jsp')
img_fp = BytesIO(resp.content)
img = Image.open(img_fp)
img.show() # 查看下载的验证码

预处理

之后进行降噪处理,通过二值化去掉后面的背景色并加深文字对比度

1
2
3
4
5
6
7
8
9
def process_img(img_path, threshold=140):
# 灰度转换
img = Image.open(img_path).convert('L')
# 二值化
pixels = img.load()
for x in range(img.width):
for y in range(img.height):
pixels[x,y] = 255 if pixels[x,y] > threshold else 0
return img

通过灰度变换将图像转换为灰度图像。灰度图像是一种具有从黑到白0-256级灰度色阶或等级的单色图像。该图像中的每个像素用8位数据表示,因此像素点值介于黑白间的256种灰度中的一种。该图像只有灰度等级,像素值0到255,表示从黑到白,没有其他颜色,如下是转换后的图像
灰度变换后的效果

图像的二值化,就是将图像上的像素点的灰度值两极分化(设置为0或255),也就是将整个图像呈现出明显的只有黑和白的视觉效果。0表示黑,255表示白。进行二值化需要找到一个合理的阈值T,用T将图像的数据分成两部分:大于T的像素群(白色)和小于T的像素群(黑色)。通过photoshop的色阶工具可以很容易找到
使用photoshop的色阶工具找到阈值

使用合理的阈值进行二值化后的效果如下
二值化后的图像

识别

经过降噪、二值化后的图片已经非常清晰了,可以直接用pytesseract库识别

1
2
3
import pytesseract as ocr

ocr.image_to_string(img,'eng')

结束语

本文不适用于有高强度变形、文字粘连、同色(深色)干扰线的验证码,但现在还有一些系统使用的是弱验证码,像如下这种验证码,都不需要做其他操作,直接用pytesseract.image_to_string就可以识别。
可直接识别的弱验证码

最后附上全部代码

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
# filename: captcha_reg.py

import requests
import pytesseract as ocr
from PIL import Image
from io import BytesIO

def retrive_img(url):
resp = requests.get(url)
img_fp = BytesIO(resp.content)
return Image.open(img_fp)

def process_img(img, threshold=140):
# 灰度转换
img = img.convert('L')
# 二值化
pixels = img.load()
for x in range(img.width):
for y in range(img.height):
pixels[x,y] = 255 if pixels[x,y] > threshold else 0
return img

def recognize(img, lang='eng'):
return ocr.image_to_string(img, lang)


if __name__ == '__main__':
img = process_img(retrive_img('http://zfcg.fjqz.gov.cn/ucapqzzfcg/portal/validate/img2.jsp'))
print(recognize(img))
img.show()