Python 轻松去除验证码干扰点,让识别不再犯难
- 引言
- 一、干扰点噪声
- 二、图片降噪
- 三、测试运行结果
- 写在最后
作者:高玉涵
时间:2024.8.29 21:52
博客:blog.csdn.net/cg_i
环境:Windows10、Python 3.11.3、PIL、Tesseract-OCR
山高月小,水落石出。
引言
在进行爬虫开发或自动化操作时,我们经常会遇到需要登录网页(或软件)的情况。而在登录过程中,验证码是一个常见且需要特别处理的问题。验证码(CAPTCHA)作为一种区分用户是计算机还是真实人类的程序,经常要求用户输入一些只有真实人类才能轻松解读的信息,以此来有效阻止自动化工具或机器人的恶意操作。处理验证码成为了爬虫和自动化操作过程中的一只拦路虎。验证码按展现形式,又分为静态验证码和动态验证码,本文主要讨论关于静态验证码的识别。
随着OCR(光学字符识别)技术日趋完善,有些组织或个人免费(大善)提供了开源的OCR引擎(如,Tesseract-OCR),使得从验证码图片中识别出文字变得容易了些。然而,”道高一尺,魔高一丈“,在此消彼长之时,验证码也相应的增加了多种”噪声“技术以干扰OCR的识别。
限于篇幅,本文关于”噪声“技术的讨论,仅限于干扰点噪声。淡到验证码,必然会涉及验证码字符的识别,我给出的例子代码中会出现Tesseract-OCR引擎的调用。这里我不会详细讨论如何使用它们以及环境搭建,此举旨在突出讨论的重心(对图像操作),我只会在实在绕不过的地方,着以笔墨,稍作解释。关于缺失部分,我会另找时间,单独开一篇另行讨论。这里提前声明,也请大家谅解。
一、干扰点噪声
干扰点噪声,作为一种常见的图像降质现象,表现为图像中随机散布的大量孤立点。这些点的灰度值与周围像素点的灰度值存在显著差异,呈现出类似椒盐噪声的特征。如图(1-1)所示为一个登录界面的示例,而图(1-2)则展示了一个带有干扰点噪声的验证码图片。
(1-1 登录界面示例)
(1-2 带干扰点的验证码)
在未经任何预处理的情况下,我们尝试使用Tesseract-OCR来识别图(1-2)中的验证码。首先,将验证码图片下载到本地,然后在图片所在的目录下执行了以下命令:
tesseract 2.png output
然而,执行结果却显示页面为空,如下所示:
Estimating resolution as 150
Empty page!!
Estimating resolution as 150
Empty page!!
从这一提示中,我们可以明显看出OCR识别未能成功。进一步查看输出文件output.txt
,其内容果然为空。这是因为干扰点噪声会严重影响OCR算法的识别效果。OCR算法依赖于图像中的文字具有相对清晰和连贯的轮廓,而噪声点的存在会破坏这些轮廓,使得算法无法正确识别文字。
二、图片降噪
通过观察,我发现验证码图片中的干扰点相对简单,因为所有干扰点的颜色都相同。针对这一特点,我可以先获取干扰点的颜色,然后清除它,以达到清除干扰点的目的。具体操作是,首先使用Windows自带的画图工具打开验证码图片,接着使用颜色选取器选取干扰点的颜色值(图2-1),之后点击编辑颜色,此时就可以查看到该颜色的RGB值(图2-2)。
(2-1 颜色选取器)
(2-2 RGB值)
干扰点清除代码:
from PIL import Image
def get_noise_color(image):
w = image.size[0]
h = image.size[1]
for x in range(w):
for y in range(h):
(r, g, b) = image.getpixel((x, y))
# 干扰点颜色
if (r,g,b) == (44,90,60):
# 用它前面像素颜色填充它,思想:相近的颜色对原图影响最小
image.putpixel((x, y), image.getpixel((x - 1, y)))
return image
def clear_save_image(image_path):
image = Image.open(image_path)
image = image.convert('RGB')
image = get_noise_color(image)
image.save("2_clear.png")
if __name__ == '__main__':
clear_save_image(r'2.png')
这段代码的具体步骤和代码解释如下:
- 导入库:
from PIL import Image
:从PIL(Python Imaging Library,现在称为Pillow)库中导入Image模块,用于图片处理。
- 定义
get_noise_color
函数:
- 这个函数接收一个Image对象作为输入。
- 首先,获取图片的宽度
w
和高度h
。 - 然后,遍历图片中的每一个像素。对于每个像素,获取其RGB颜色值。
- 如果某个像素的颜色是
(44, 90, 60)
(噪点颜色),则将这个像素的颜色替换为其前一个像素的颜色(即(x - 1, y)
位置的颜色)。 - 最后,返回处理后的Image对象。
- 定义
clear_save_image
函数:
- 这个函数接收一个图片路径
image_path
作为输入。 - 使用
Image.open(image_path)
打开并读取图片。 - 使用
image.convert('RGB')
将图片转换为RGB模式,确保图片有三个颜色通道。 - 调用
get_noise_color
函数去除图片中的噪点。 - 将处理后的图片保存为"2_clear.png"。
- 主函数:
- 如果直接运行这个脚本,将调用
clear_save_image
函数,传入一个图片路径(这里是’2.png’),对图片进行处理并保存。
三、测试运行结果
首先,执行这个Pyhton程序:
python .\clear_noisy.py
执行后,会生成一个名为2_clear.png
的图片(如图3-1所示),这是清除噪点后的验证码图片。
(图 3-1 清除噪点后的验证码图片)
接着,我们使用Tesseract-OCR来识别处理后的图像。执行以下命令:
tesseract 2_clear.png output
Estimating resolution as 133
此时,明显可以看出较上次,输出的结果明显不同。为了进一步验证,我们打开output.txt
文件,可以看出验证码已被正常识别出来了(如图 3-2 所示)。
(图 3-2 验证码值)
写在最后
首先,衷心感谢你坚持阅读至此。或许在你看来,这篇文章的内容并不复杂,甚至觉得不过如此。但无论你信不信,上述提供的代码背后,是我耗费了大量精力、历经诸多曲折、不断尝试与修正的成果。在无数次的测试与修改中,我删除了大量代码,经历了无数次的失败。最终,在灵光一闪的瞬间,我才得出了这几行简洁而有效的代码。这个过程虽然充满挑战,但也让我深刻体会到了编程的魅力与乐趣。希望我的分享能对你有所启发,也期待你在编程的道路上不断探索与成长。