当前位置: 首页 > news >正文

Python 轻松去除验证码干扰点,让识别不再犯难

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 Imagedef 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 imagedef 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')

这段代码的具体步骤和代码解释如下:

  1. 导入库:
  • from PIL import Image:从PIL(Python Imaging Library,现在称为Pillow)库中导入Image模块,用于图片处理。
  1. 定义get_noise_color函数:
  • 这个函数接收一个Image对象作为输入。
  • 首先,获取图片的宽度w和高度h
  • 然后,遍历图片中的每一个像素。对于每个像素,获取其RGB颜色值。
  • 如果某个像素的颜色是(44, 90, 60)(噪点颜色),则将这个像素的颜色替换为其前一个像素的颜色(即(x - 1, y)位置的颜色)。
  • 最后,返回处理后的Image对象。
  1. 定义clear_save_image函数:
  • 这个函数接收一个图片路径image_path作为输入。
  • 使用Image.open(image_path)打开并读取图片。
  • 使用image.convert('RGB')将图片转换为RGB模式,确保图片有三个颜色通道。
  • 调用get_noise_color函数去除图片中的噪点。
  • 将处理后的图片保存为"2_clear.png"。
  1. 主函数:
  • 如果直接运行这个脚本,将调用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 验证码值)

写在最后

首先,衷心感谢你坚持阅读至此。或许在你看来,这篇文章的内容并不复杂,甚至觉得不过如此。但无论你信不信,上述提供的代码背后,是我耗费了大量精力、历经诸多曲折、不断尝试与修正的成果。在无数次的测试与修改中,我删除了大量代码,经历了无数次的失败。最终,在灵光一闪的瞬间,我才得出了这几行简洁而有效的代码。这个过程虽然充满挑战,但也让我深刻体会到了编程的魅力与乐趣。希望我的分享能对你有所启发,也期待你在编程的道路上不断探索与成长。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【职责链】设计模式:构建灵活的请求处理系统
  • 【C++】—— 内存管理
  • 2.【R语言】RStudio的下载和安装
  • 【产品那些事】什么是软件成分分析(SCA)?
  • Java大文件下载方案(vue+饿了么):分片下载、断点续载!
  • MySQL——多表操作(三)连接查询(2)内连接
  • 深入理解 Go 语言并发编程底层原理
  • TCP、HTTP以及RPC的梳理
  • 有关Prompt Engineering(提示词工程)的一些总结
  • 低代码门户技术:赋能业务灵活性与创新的新时代
  • go 开发小技巧
  • 解决Spring Boot中Druid连接池“discard long time none received connection“警告
  • Unity(2022.3.41LTS) - 地形
  • 口语笔记——虚拟语气
  • 智慧灯塔,照亮企业AI Agent实施明路
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • 【comparator, comparable】小总结
  • Cumulo 的 ClojureScript 模块已经成型
  • Flannel解读
  • JAVA_NIO系列——Channel和Buffer详解
  • JS 面试题总结
  • MySQL几个简单SQL的优化
  • oschina
  • Promise面试题2实现异步串行执行
  • Vue 2.3、2.4 知识点小结
  • 关于extract.autodesk.io的一些说明
  • 技术胖1-4季视频复习— (看视频笔记)
  • 排序算法学习笔记
  • 系统认识JavaScript正则表达式
  • 一个完整Java Web项目背后的密码
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • C# - 为值类型重定义相等性
  • !$boo在php中什么意思,php前戏
  • # Redis 入门到精通(七)-- redis 删除策略
  • #pragma once
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (C11) 泛型表达式
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (pytorch进阶之路)扩散概率模型
  • (备份) esp32 GPIO
  • (二)c52学习之旅-简单了解单片机
  • (二开)Flink 修改源码拓展 SQL 语法
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (四)库存超卖案例实战——优化redis分布式锁
  • (学习日记)2024.01.09
  • (学习日记)2024.01.19
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (转)Scala的“=”符号简介
  • ./和../以及/和~之间的区别
  • .bat批处理(六):替换字符串中匹配的子串
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料
  • .NET delegate 委托 、 Event 事件,接口回调