依赖的安装
pip install pillow
引入 pillow
from PIL import Image
载入图片
image = Image.open('CAPTCHA.png')
灰度
imgry = image.convert('L')
二值化
def get_bin_table(threshold=128):
'''获取灰度转二值的映射table,0表示黑色,1表示白色'''
table = []
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
return table
binary = imgry.point(get_bin_table(), '1')
降噪
def sum_9_region_new(img, x, y):
'''确定噪点 '''
cur_pixel = img.getpixel((x, y)) # 当前像素点的值
width = img.width
height = img.height
if cur_pixel == 1: # 如果当前点为白色区域,则不统计邻域值
return 0
# 因当前图片的四周都有黑点,所以周围的黑点可以去除
if y < 3: # 本例中,前两行的黑点都可以去除
return 1
elif y > height - 3: # 最下面两行
return 1
else: # y不在边界
if x < 3: # 前两列
return 1
elif x == width - 1: # 右边非顶点
return 1
else: # 具备9领域条件的
sum = img.getpixel((x - 1, y - 1)) \
+ img.getpixel((x - 1, y)) \
+ img.getpixel((x - 1, y + 1)) \
+ img.getpixel((x, y - 1)) \
+ cur_pixel \
+ img.getpixel((x, y + 1)) \
+ img.getpixel((x + 1, y - 1)) \
+ img.getpixel((x + 1, y)) \
+ img.getpixel((x + 1, y + 1))
return 9 - sum
def collect_noise_point(img):
'''收集所有的噪点'''
noise_point_list = []
for x in range(img.width):
for y in range(img.height):
res_9 = sum_9_region_new(img, x, y)
if (0 < res_9 < 3) and img.getpixel((x, y)) == 0: # 找到孤立点
pos = (x, y)
noise_point_list.append(pos)
return noise_point_list
def remove_noise_pixel(img, noise_point_list):
'''根据噪点的位置信息,消除二值图片的黑点噪声'''
for item in noise_point_list:
img.putpixel((item[0], item[1]), 1)
noise_point_list = collect_noise_point(binary)
remove_noise_pixel(binary, noise_point_list)
分割字符 和 归一化 都是为了方便识别,大多数情况下 分割字符 和 归一化 都是难点, 这里就直接交给 tesseract 识别了。
保存预处理的图片
image_path = 'pre.png'
binary.save(image_path)
调用 tesseract 命令识别
cmd = 'tesseract ' + image_path + ' stdout -l osd --psm 7 digits'
res = os.popen(cmd)
print(res.buffer.read().decode('utf-8'))
这是上文出现的 tesseract 命令
tesseract image_path stdout -l osd --psm 7 digits
digits 识别数字和英文字母
osd = Orientation and script detection (方向 和 脚本 检测) 其实笔者并不理解,为什么 osd 会作为一种语言的选项
psm = Page segmentation modes (页面 分割 模式)
可以通过这两个命令来查看命令行的帮助
tesseract --help
tesseract --help-extra
tessedit_char_whitelist 0123456789abcdefghijklnmopqrstuvwsyz
tesseract image_path stdout -l osd --psm 7 digits_new
限定要识别的文字 能有效提高识别的准确率。
from PIL import Image
image = Image.open('CAPTCHA.png')
imgry = image.convert('L')
def get_bin_table(threshold=128):
'''获取灰度转二值的映射table,0表示黑色,1表示白色'''
table = []
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
return table
binary = imgry.point(get_bin_table(), '1')
def sum_9_region_new(img, x, y):
'''确定噪点 '''
cur_pixel = img.getpixel((x, y)) # 当前像素点的值
width = img.width
height = img.height
if cur_pixel == 1: # 如果当前点为白色区域,则不统计邻域值
return 0
# 因当前图片的四周都有黑点,所以周围的黑点可以去除
if y < 3: # 本例中,前两行的黑点都可以去除
return 1
elif y > height - 3: # 最下面两行
return 1
else: # y不在边界
if x < 3: # 前两列
return 1
elif x == width - 1: # 右边非顶点
return 1
else: # 具备9领域条件的
sum = img.getpixel((x - 1, y - 1)) \
+ img.getpixel((x - 1, y)) \
+ img.getpixel((x - 1, y + 1)) \
+ img.getpixel((x, y - 1)) \
+ cur_pixel \
+ img.getpixel((x, y + 1)) \
+ img.getpixel((x + 1, y - 1)) \
+ img.getpixel((x + 1, y)) \
+ img.getpixel((x + 1, y + 1))
return 9 - sum
def collect_noise_point(img):
'''收集所有的噪点'''
noise_point_list = []
for x in range(img.width):
for y in range(img.height):
res_9 = sum_9_region_new(img, x, y)
if (0 < res_9 < 3) and img.getpixel((x, y)) == 0: # 找到孤立点
pos = (x, y)
noise_point_list.append(pos)
return noise_point_list
def remove_noise_pixel(img, noise_point_list):
'''根据噪点的位置信息,消除二值图片的黑点噪声'''
for item in noise_point_list:
img.putpixel((item[0], item[1]), 1)
noise_point_list = collect_noise_point(binary)
remove_noise_pixel(binary, noise_point_list)
cmd = 'tesseract ' + image_path + ' stdout -l osd --psm 7 digits'
res = os.popen(cmd)
print(res.buffer.read().decode('utf-8'))