Python图像处理之图片验证码识别
在上一篇博客Python图像处理之图片文字识别(OCR)中我们介绍了在Python中如何利用Tesseract软件来识别图片中的英文与中文,本文将具体介绍如何在Python中利用Tesseract软件来识别验证码(数字加字母)。
我们在网上浏览网页或注册账号时,会经常遇到验证码(CAPTCHA),如下图:
本文将具体介绍如何利用Python的图像处理模块pillow和OCR模块pytesseract来识别上述验证码(数字加字母)。
我们识别上述验证码的算法过程如下:
- 将原图像进行灰度处理,转化为灰度图像;
- 获取图片中像素点数量最多的像素(此为图片背景),将该像素作为阈值进行二值化处理,将灰度图像转化为黑白图像(用来提高识别的准确率);
- 去掉黑白图像中的噪声,噪声定义为:以该点为中心的九宫格的黑点的数量小于等于4;
- 利用pytesseract模块识别,去掉识别结果中的特殊字符,获得识别结果。
我们的图片如下(共66张图片):
完整的Python代码如下:
import os import pytesseract from PIL import Image from collections import defaultdict # tesseract.exe所在的文件路径 pytesseract.pytesseract.tesseract_cmd = 'C://Program Files (x86)/Tesseract-OCR/tesseract.exe' # 获取图片中像素点数量最多的像素 def get_threshold(image): pixel_dict = defaultdict(int) # 像素及该像素出现次数的字典 rows, cols = image.size for i in range(rows): for j in range(cols): pixel = image.getpixel((i, j)) pixel_dict[pixel] += 1 count_max = max(pixel_dict.values()) # 获取像素出现出多的次数 pixel_dict_reverse = {v:k for k,v in pixel_dict.items()} threshold = pixel_dict_reverse[count_max] # 获取出现次数最多的像素点 return threshold # 按照阈值进行二值化处理 # threshold: 像素阈值 def get_bin_table(threshold): # 获取灰度转二值的映射table table = [] for i in range(256): rate = 0.1 # 在threshold的适当范围内进行处理 if threshold*(1-rate)<= i <= threshold*(1+rate): table.append(1) else: table.append(0) return table # 去掉二值化处理后的图片中的噪声点 def cut_noise(image): rows, cols = image.size # 图片的宽度和高度 change_pos = [] # 记录噪声点位置 # 遍历图片中的每个点,除掉边缘 for i in range(1, rows-1): for j in range(1, cols-1): # pixel_set用来记录该店附近的黑色像素的数量 pixel_set = [] # 取该点的邻域为以该点为中心的九宫格 for m in range(i-1, i+2): for n in range(j-1, j+2): if image.getpixel((m, n)) != 1: # 1为白色,0位黑色 pixel_set.append(image.getpixel((m, n))) # 如果该位置的九宫内的黑色数量小于等于4,则判断为噪声 if len(pixel_set) <= 4: change_pos.append((i,j)) # 对相应位置进行像素修改,将噪声处的像素置为1(白色) for pos in change_pos: image.putpixel(pos, 1) return image # 返回修改后的图片 # 识别图片中的数字加字母 # 传入参数为图片路径,返回结果为:识别结果 def OCR_lmj(img_path): image = Image.open(img_path) # 打开图片文件 imgry = image.convert('L') # 转化为灰度图 # 获取图片中的出现次数最多的像素,即为该图片的背景 max_pixel = get_threshold(imgry) # 将图片进行二值化处理 table = get_bin_table(threshold=max_pixel) out = imgry.point(table, '1') # 去掉图片中的噪声(孤立点) out = cut_noise(out) #保存图片 # out.save('E://figures/img_gray.jpg') # 仅识别图片中的数字 #text = pytesseract.image_to_string(out, config='digits') # 识别图片中的数字和字母 text = pytesseract.image_to_string(out) # 去掉识别结果中的特殊字符 exclude_char_list = ' .:\\|\'\"?![],()~@#$%^&*_+-={};<>/¥' text = ''.join([x for x in text if x not in exclude_char_list]) #print(text) return text def main(): # 识别指定文件目录下的图片 # 图片存放目录figures dir = 'E://figures' correct_count = 0 # 图片总数 total_count = 0 # 识别正确的图片数量 # 遍历figures下的png,jpg文件 for file in os.listdir(dir): if file.endswith('.png') or file.endswith('.jpg'): # print(file) image_path = '%s/%s'%(dir,file) # 图片路径 answer = file.split('.')[0] # 图片名称,即图片中的正确文字 recognizition = OCR_lmj(image_path) # 图片识别的文字结果 print((answer, recognizition)) if recognizition == answer: # 如果识别结果正确,则total_count加1 correct_count += 1 total_count += 1 print('Total count: %d, correct: %d.'%(total_count, correct_count)) ''' # 单张图片识别 image_path = 'E://figures/code (1).jpg' OCR_lmj(image_path) ''' main()
运行结果如下:
('101659', '101659') ('111073', '111073') ('114510', '114510') ('118235', '118235') ('124677', '124677') ('147291', '147291') ('169147', '169147') ('185302', '185302') ('23YB', '23YB') ('262051', '262051') ('2HED', '2MED') ('315386', '315386') ('3D7K', '3D7K') ('3DYH', '3DYH') ('3QG8', '30G8') ('3XNR', 'EXNR') ('44G5', '44G5') ('470259', '470259') ('515413', '515413') ('522351', '522351') ('539824', '539824') ('5CVL', 'SCVL') ('642689', '642689') ('671991', '671991') ('672838', '672838') ('6F5Y', '6F5Y') ('6USB', 'GUSB') ('703167', '703167') ('765120', '765120') ('779931', '779931') ('8UEF', '8SUEF') ('905857', '905857') ('9H4H', '9H4H') ('9SK1', 'OSK1') ('BDP4', 'BDP4') ('DXV3', 'DXV3') ('E78Y', 'E78Y') ('EAHR', 'EAHR') ('F585', 'Fss§') ('FBV8', 'FBV8') ('FJKK', 'FJKK') ('GXKQ', 'GXKQ') ('H7Y9', 'H7Y9') ('J4LJ', 'J4LJ') ('J8YH', 'J8YH') ('JCDL', 'JCDL') ('JTX2', 'JTX2') ('JYLH', 'JYLH') ('KFYA', 'KFYA') ('L3VZ', 'L3VZ') ('LCGV', 'LCGV') ('LKEK', 'LKEK') ('N3FJ', 'N3FJ') ('PJZN', 'PJZN') ('PNDQ', 'PNDQ') ('Q7HP', 'Q7HP') ('QSHU', 'QSHU') ('R1RN', 'RLRN') ('RPNX', 'RPNX') ('TUKG', 'TUKG') ('U9G3', 'U9G3') ('UZAH', 'UZAH') ('V6P9', 'very') ('Y18D', '18D') ('Y237', 'Y237') ('ZZT5', '2215') Total count: 66, correct: 54.
我们可以看到图片识别的正确率为80%以上,其中数字类图片的识别正确率为100%.
我们可以在图片识别方面的算法再加改进,以提高图片识别的正确率。当然,以上算法并不是对所有验证码都适用,不同的验证码需要用不同的图片处理算法。
注意:本人现已开通两个微信公众号: 因为Python(微信号为:python_math)以及轻松学会Python爬虫(微信号为:easy_web_scrape), 欢迎大家关注哦~~
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
【Java小工匠聊密码学】--消息摘要--HMAC算法
1、什么是HMAC HMAC是密钥相关的消息认证码,HMAC运算利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。 2、HMAC用途 我们使用MD和SHA 消息摘要算法,可以保证数据的完整性。但是在网络传输场景下,消息发送者,仅发送原始数据和数据摘要信息是,黑客可以伪装原始数据和数据摘要信息,达到攻击的目的,HMAC算法通过密钥和数据共同生成 消息摘要,黑客在不知道密钥的情况下,伪造数据和消息摘要难度进一步加大。 消息发送 3、HMAC算法分类 算法种类 摘要长度 HmacMD5 128 HmacSHA1 160 HmacSHA256 256 HmacSHA384 384 HmacSHA512 512 4、HMAC算法实现 4.1 JDK 算法实现 package lzf.cipher.jdk; import java.nio.charset.Charset; import javax.crypto.KeyGenerator; import javax.crypto.Mac; import javax.crypto.SecretKey; import ja...
- 下一篇
【Java小工匠聊密码学】--消息摘要--概述
1、消息摘要概述 数据摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名、数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密。 2、消息摘要算法特点 2.1 变成输入、定长输出 无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。例如应用MD5算法摘要的消息有128个比特位,用SHA-1算法摘要的消息最终有160比特位的输出。 2.2 输入不同、摘要不同,输入相同、摘要相同 只要输入的消息不同,对其进行摘要以后产生的摘要消息也必不相同;但相同的输入必会产生相同的输出。这正是好的消息摘要算法所具有的性质:输入改变了,输出也就改变了;两条相似的消息的摘要确不相近,甚至会大相径庭。从理论上来说,不管使用什么样的摘要算法,必然存在2个不同的消息,对应同样的摘要。因为输入是一个无穷集合,而输出是一个有限集合,所以从数学上来说,必然存在多对一的关系。但是实际上,很难或者说根本不可能人为的造出具有同样摘要的2个不同消息。 2.3 单向、不可逆、散列值不同、原始值不同 消息摘要是单向、不可逆的。只能进行正向的信息摘要,而无法从摘要中恢复出任何...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS关闭SELinux安全模块
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS6,CentOS7官方镜像安装Oracle11G
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19
- CentOS6,7,8上安装Nginx,支持https2.0的开启