python tesseract验证码识别(验证码未粘连)

2023-05-16

需要的库和工具及安装

其中会用到以下几个库和工具:

工具:

tesseract

tesseract下载地址:https://digi.bib.uni-mannheim.de/tesseract/

1.下载适合自己版本(32或者64位)的非dev的exe文件,然后一路安装下去。经过多次测试,不同版本的tesseract识别的结果会不同,我试了五六个版本,最后使用tesseract-ocr-w64-setup-v5.0.0-alpha.20210506.exe 版本识别成功率最高。

:如果需要支持多国语言,到这个步骤的时候它勾选上,默认支持英文:

0

2.配置环境变量 

path 里面配置tesseract的安装路径:

 3.验证安装是否成功:

cmd,然后输入验证tesseract和验证tesseract -v 正常显示即可

 pillow 和 pytesseract 两个库

pip install pillow -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install pytesseract -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

配置pytesseract库:

找到pytesseract 库的pytesseract.py文件,打开该.py文件,找到 tesseract_cmd,改变它的值为刚才安装 tesseract.exe 的路径。

0

安装cv2库:

pip3 install opencv-python

正文

在python爬虫爬取某些网站的验证码的时候可能会遇到验证码识别的问题,现在的验证码大多分为四类:

1、识图的验证码   2、需要计算的验证码   3、通过滑动滑块的验证码   4、语音的验证码

本文针对最简单的识图验证码,识别验证码中的英文数字。

识别验证码通常是这几个步骤:

 1、灰度处理:把彩色的验证码图片转为灰色的图片

 2、二值化:将图片处理为只有黑白两色的图片

 3、去除边框:去除验证码图片的边框,去除边框就是遍历像素点,找到四个边框上的所有点,把他们都改为白色,如果没有边框可以不用。

 4、降噪:去除掉验证码图片内的干扰条件,比如西线和点。

 5、切割字符或者倾斜度矫正:切割字符对验证码内的内容进行单个的切割,一般用于验证码粘连或者计算验证码。

 6、训练字体库

 7、识别

 如果验证码图片清晰度很高,是直接图片保存下来的。(不是截图)可以用以下代码

import re

import numpy
from PIL import Image
from pytesseract import *
from fnmatch import fnmatch
from queue import Queue
import cv2
import os


'''
需要建两个文件夹,code_dir文件夹存放验证码图片,
out_img文件夹 存放处理后的验证码图片
'''


class LdenVerifiCode:
    filedir = 'D:/logs/code_dir'  # 存放验证码的文件夹
    code_out_folder = 'D:/logs/out_img'

    def clear_border(self, img, img_name):
        '''去除边框
        '''

        # filename = self.code_out_folder + img_name.split('.')[0] + '-clearBorder.jpg'
        filename = os.path.join(self.code_out_folder, img_name.split('.')[0] + '-clearBorder.png')
        h, w = img.shape[:2]
        for y in range(0, w):
            for x in range(0, h):
                # if y ==0 or y == w -1 or y == w - 2:
                if y < 4 or y > w - 4:
                    img[x, y] = 255
                # if x == 0 or x == h - 1 or x == h - 2:
                if x < 4 or x > h - 4:
                    img[x, y] = 255

        cv2.imwrite(filename, img)
        return img

    def interference_line(self, img, img_name):
        '''
        干扰线降噪
        '''

        # filename =  self.code_out_folder + img_name.split('.')[0] + '-interferenceline.jpg'
        filename = os.path.join(self.code_out_folder, img_name.split('.')[0] + '-interferenceline.png')
        h, w = img.shape[:2]
        # !!!opencv矩阵点是反的
        # img[1,2] 1:图片的高度,2:图片的宽度
        for y in range(1, w - 1):
            for x in range(1, h - 1):
                count = 0
                if img[x, y - 1] > 245:
                    count = count + 1
                if img[x, y + 1] > 245:
                    count = count + 1
                if img[x - 1, y] > 245:
                    count = count + 1
                if img[x + 1, y] > 245:
                    count = count + 1
                if count > 2:
                    img[x, y] = 255
        cv2.imwrite(filename, img)
        return img

    def interference_point(self, img, img_name, x=0, y=0):
        """点降噪
        9邻域框,以当前点为中心的田字框,黑点个数
        :param x:
        :param y:
        :return:
        """
        # filename =  './out_img/' + img_name.split('.')[0] + '-interferencePoint.jpg'
        filename = os.path.join(self.code_out_folder, img_name.split('.')[0] + '-cutting.png')
        # todo 判断图片的长宽度下限
        cur_pixel = img[x, y]  # 当前像素点的值
        height, width = img.shape[:2]

        for y in range(0, width - 1):
            for x in range(0, height - 1):
                if y == 0:  # 第一行
                    if x == 0:  # 左上顶点,4邻域
                        # 中心点旁边3个点
                        sum = int(cur_pixel) \
                              + int(img[x, y + 1]) \
                              + int(img[x + 1, y]) \
                              + int(img[x + 1, y + 1])
                        if sum <= 2 * 245:
                            img[x, y] = 0
                    elif x == height - 1:  # 右上顶点
                        sum = int(cur_pixel) \
                              + int(img[x, y + 1]) \
                              + int(img[x - 1, y]) \
                              + int(img[x - 1, y + 1])
                        if sum <= 2 * 245:
                            img[x, y] = 0
                    else:  # 最上非顶点,6邻域
                        sum = int(img[x - 1, y]) \
                              + int(img[x - 1, y + 1]) \
                              + int(cur_pixel) \
                              + int(img[x, y + 1]) \
                              + int(img[x + 1, y]) \
                              + int(img[x + 1, y + 1])
                        if sum <= 3 * 245:
                            img[x, y] = 0
                elif y == width - 1:  # 最下面一行
                    if x == 0:  # 左下顶点
                        # 中心点旁边3个点
                        sum = int(cur_pixel) \
                              + int(img[x + 1, y]) \
                              + int(img[x + 1, y - 1]) \
                              + int(img[x, y - 1])
                        if sum <= 2 * 245:
                            img[x, y] = 0
                    elif x == height - 1:  # 右下顶点
                        sum = int(cur_pixel) \
                              + int(img[x, y - 1]) \
                              + int(img[x - 1, y]) \
                              + int(img[x - 1, y - 1])

                        if sum <= 2 * 245:
                            img[x, y] = 0
                    else:  # 最下非顶点,6邻域
                        sum = int(cur_pixel) \
                              + int(img[x - 1, y]) \
                              + int(img[x + 1, y]) \
                              + int(img[x, y - 1]) \
                              + int(img[x - 1, y - 1]) \
                              + int(img[x + 1, y - 1])
                        if sum <= 3 * 245:
                            img[x, y] = 0
                else:  # y不在边界
                    if x == 0:  # 左边非顶点
                        sum = int(img[x, y - 1]) \
                              + int(cur_pixel) \
                              + int(img[x, y + 1]) \
                              + int(img[x + 1, y - 1]) \
                              + int(img[x + 1, y]) \
                              + int(img[x + 1, y + 1])

                        if sum <= 3 * 245:
                            img[x, y] = 0
                    elif x == height - 1:  # 右边非顶点
                        sum = int(img[x, y - 1]) \
                              + int(cur_pixel) \
                              + int(img[x, y + 1]) \
                              + int(img[x - 1, y - 1]) \
                              + int(img[x - 1, y]) \
                              + int(img[x - 1, y + 1])

                        if sum <= 3 * 245:
                            img[x, y] = 0
                    else:  # 具备9领域条件的
                        sum = int(img[x - 1, y - 1]) \
                              + int(img[x - 1, y]) \
                              + int(img[x - 1, y + 1]) \
                              + int(img[x, y - 1]) \
                              + int(cur_pixel) \
                              + int(img[x, y + 1]) \
                              + int(img[x + 1, y - 1]) \
                              + int(img[x + 1, y]) \
                              + int(img[x + 1, y + 1])
                        if sum <= 4 * 245:
                            img[x, y] = 0
        cv2.imwrite(filename, img)
        return img

    def _get_dynamic_binary_image(self, filedir, img_name):
        '''
        自适应阀值二值化
        '''

        # filename = self.code_out_folder + img_name.split('.')[0] + '-binary.jpg'
        filename = os.path.join(self.code_out_folder, img_name.split('.')[0] + '-binary.png')
        img_name = filedir + '/' + img_name
        print('开始识别验证码:' + img_name)
        im = cv2.imread(img_name)
        im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
        th1 = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 1)
        cv2.imwrite(filename, th1)
        return th1

    def _get_static_binary_image(self, img, threshold=140):
        '''
        手动二值化
        '''

        img = Image.open(img)
        img = img.convert('L')
        pixdata = img.load()
        w, h = img.size
        for y in range(h):
            for x in range(w):
                if pixdata[x, y] < threshold:
                    pixdata[x, y] = 0
                else:
                    pixdata[x, y] = 255

        return img

    def main(self, img_name):

        # 自适应阈值二值化
        im = self._get_dynamic_binary_image(self.filedir, img_name)

        # 去除边框
        im = self.clear_border(im, img_name)

        # 对图片进行干扰线降噪
        im = self.interference_line(im, img_name)

        # 对图片进行点降噪
        self.interference_point(im, img_name)

        # code_file ='./out_img/%s-cutting.jpg' % img_name.split('.')[0]
        code_file = os.path.join(self.code_out_folder, '%s-cutting.png' % img_name.split('.')[0])
        str_img = image_to_string(Image.open(code_file))  # 图片转文字
        cop = re.compile("[^a-z^A-Z^0-9]")  # 匹配不是英文大小写、数字的其他字符,去掉特殊字符
        code_results = cop.sub('', str_img)  # 将string1中匹配到的字符替换成空字符
        print('识别为:%s' % code_results)
        return code_results

if __name__ == '__main__':
    lvc = LdenVerifiCode()
    lvc.main('191704-ele.png')

如果是通过定位元素坐标,然后截图下来的验证码可以用以下代码:

import re

import numpy
from PIL import Image
from pytesseract import *
from fnmatch import fnmatch
from queue import Queue
import cv2
import os

'''
需要建两个文件夹,code_dir文件夹存放验证码图片,
out_img文件夹 存放处理后的验证码图片
'''


class LdenVerifiCode:
    filedir = 'E:/logs/code_dir'  # 存放验证码的文件夹
    code_out_folder = 'E:/logs/out_img'

    def clear_border(self, filedir, img_name):
        '''去除边框
        '''
        img_name = filedir + '/' + img_name
        img = cv2.imread(img_name)
        filename = os.path.join(self.code_out_folder, img_name.split('.')[0] + '-clearBorder.png')
        h, w = img.shape[:2]
        for y in range(0, w):
            for x in range(0, h):
                # if y ==0 or y == w -1 or y == w - 2:
                if y < 4 or y > w - 4:
                    img[x, y] = 255
                # if x == 0 or x == h - 1 or x == h - 2:
                if x < 4 or x > h - 4:
                    img[x, y] = 255

        cv2.imwrite(filename, img)
        return filename

    def clearNoise(self,imageFile,img_name, x=0, y=0):
        if os.path.exists(imageFile):
            image = Image.open(imageFile)
            image = image.convert('L')
            image = numpy.asarray(image)
            image = (image > 135) * 255
            image = Image.fromarray(image).convert('RGB')
            filename = os.path.join(self.code_out_folder, img_name.split('.')[0] + '-cutting.png')
            image.save(filename)
            return image

    def main(self, img_name):
        # 去除边框
        filename = self.clear_border(self.filedir, img_name)
        self.clearNoise(filename,img_name)
        code_file = os.path.join(self.code_out_folder, '%s-cutting.png' % img_name.split('.')[0])
        str_img = image_to_string(Image.open(code_file))  # 图片转文字
        cop = re.compile("[^a-z^A-Z^0-9]")  # 匹配不是英文大小写、数字的其他字符,去掉特殊字符
        code_results = cop.sub('', str_img)  # 将string1中匹配到的字符替换成空字符
        print('识别为:%s' % code_results)
        return code_results

if __name__ == '__main__':
    lvc = LdenVerifiCode()
    lvc.main('145512-ele.png')

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python tesseract验证码识别(验证码未粘连) 的相关文章

  • Docker 进程被神秘的“Killed”消息杀死

    在 docker 容器中运行 python 脚本 一切似乎都运行顺利 看到一些 STDOUT 消息 大约 5 分钟后我得到了Killed消息 没有进一步的解释 并且该过程停止 查询数据库可能是磁盘空间问题 也可能是 OOM 问题 我不确定
  • 使用 Marshmallow 中的数据更新行 (SQLAlchemy)

    我正在使用 Flask Flask SQLAlchemy Flask Marshmallow marshmallow sqlalchemy 尝试实现 REST api PUT 方法 我还没有找到任何使用 SQLA 和 Marshmallow
  • 刷新访问令牌时出现“invalid_grant”错误的情况?

    最近我一直在为这个问题揪心 一些背景 使用oauth2客户端 https code google com p google api python client 库来管理用户的令牌 这些令牌用于定期并发执行各种后台任务 每次要为用户运行其中一
  • OpenCV Python 删除图像中的某些对象

    我正在使用带有 opencv 和 numpy 的 python 来检测天文中的星星 例如这个1 https i stack imgur com AKwEJ jpg图片 使用模板匹配 我可以用阈值检测星星 单击 2 2 https i sta
  • 同情因子简单关系

    我在 sympy 中有一个简单的因式分解问题 无法解决 我在 sympy 处理相当复杂的积分方面取得了巨大成功 但我对一些简单的事情感到困惑 如何得到 phi 2 2 phi phi 0 phi 0 2 8 因式分解 phi phi 0 2
  • 如何编写高效的配对算法?

    我需要一种算法的帮助 该算法可以有效地将人们分组 并确保以前的配对不会重复 例如 假设我们有 10 位候选人 candidates 0 1 2 3 4 5 6 7 8 9 并假设我们有一个先前匹配的字典 这样每个键值对即candidate
  • 将 stdout 重定向到 Python 中的文件? [复制]

    这个问题在这里已经有答案了 如何将 stdout 重定向到 Python 中的任意文件 当长时间运行的 Python 脚本 例如 Web 应用程序 从 ssh 会话内启动并处于后台 并且 ssh 会话关闭时 应用程序将引发 IOError
  • 使用 K 均值聚类 OpenCV 进行交通标志分割

    I used K Means Clustering to perform segmentation on this traffic sign as shown below 这些是我的代码 读取图像并模糊 img cv imread 000
  • Python 中的二进制相移键控

    我目前正在编写一些代码 以使用音频转换通过激光传输消息 文件 和其他数据 我当前的代码使用 python 中 binascii 模块中的 hexlify 函数将数据转换为二进制 然后为 1 发出一个音调 为 0 发出不同的音调 这在理论上是
  • 用于打印 C/C++ 文件的所有函数定义的 Python 脚本

    我想要一个 python 脚本来打印 C C 文件中定义的所有函数的列表 e g abc c定义两个函数为 void func1 int func2 int i printf d i return 1 我只想搜索文件 abc c 并打印其中
  • 在 C# 中实例化 python 类

    我已经用 python 编写了一个类 我想通过 IronPython 将其包装到 net 程序集中 并在 C 应用程序中实例化 我已将该类迁移到 IronPython 创建了一个库程序集并引用了它 现在 我如何真正获得该类的实例 该类看起来
  • Python NLP 英式英语与美式英语

    我目前正在用Python 进行NLP 工作 然而 在我的语料库中 既有英式英语也有美式英语 实现 实现 我正在考虑将英式英语转换为美式英语 但是 我没有找到一个好的工具 包来做到这一点 有什么建议么 我也找不到包 但试试这个 请注意 我必须
  • 将 JSON 字符串传递给 Django 模板

    我一直在用头撞墙 试图找出为什么我无法将从 Django 模型生成的 JSON 字符串传递到模板的 javascript 静态文件中 事实证明 问题不在模型级别 使用serializers serialize 在脚本本身中放入相同的字符串将
  • 检查对象数组中的多个属性匹配

    我有一个对象数组 它们都是相同的对象类型 并且它们有多个属性 有没有办法返回一个较小的对象数组 其中所有属性都与测试用例 字符串匹配 无论该属性类型是什么 使用列表理解all http docs python org 3 library f
  • 将 ASCII 字符转换为“”unicode 表示法的脚本

    我正在对 Linux 区域设置文件进行一些更改 usr share i18n locales like pt BR 并且需要格式化字符串 例如 d m Y H M 必须以 Unicode 指定 其中每个 在本例中为 ASCII 字符表示为
  • tweepy 流到 sqlite 数据库 - 语法错误[重复]

    这个问题在这里已经有答案了 可能的重复 tweepy 流到 sqlite 数据库 语法无效 https stackoverflow com questions 9434205 tweepy stream to sqlite database
  • 通过子类化 `io.TextIOWrapper` 来子类化文件 - 但它的构造函数有什么签名?

    我正在尝试子类化io TextIOWrapper下列的这个帖子 https stackoverflow com a 23796737 974555 虽然我的目标不同 以此开始 注意 动机 https stackoverflow com a
  • 对 pandas 数据框中的每一列应用函数

    我如何以更多的熊猫方式编写以下函数 def calculate df columns mean self df means for column in df columns columns tolist cleaned data self
  • 带有整数的 np.sqrt 和 where 条件返回错误结果

    当我将 numpy sqrt 方法应用于带有 a 的整数数组时 我得到了奇怪的结果where健康 状况 见下文 对于整数 a np array 1 4 9 np sqrt a where a gt 5 Out 3 array 0 0 5 3
  • 使用Python的timeit获取“全局名称'foo'未定义”

    我想知道执行一条Python语句需要多少时间 所以我上网查了一下 发现标准库提供了一个名为timeit http docs python org library timeit html旨在做到这一点 import timeit def fo

随机推荐

  • C语言十进制转八进制、十六进制以及十六进制转十进制、八进制

    以下程序的输出结果是 main int a 61 20 printf 34 d o x n 34 a a a 看到这个题目首先我们要明白 o 和 x代表的是什么意思 o代表的是输出该数字的八进制 x代表的是输出该数字的十六进制 1 题目给出
  • 解决Mybatis分页插件PageHelper自动添加limit导致分页失败问题

    目录 1 问题描述2 解决方案2 1 方案一2 2 方案二 3 完成效果4 一点困惑5 参考文献 1 问题描述 今天在完善项目的时候 xff0c 有一个需求就是给我的评论区实现分页显示评论数 xff0c 但是当自己运行的时候点击查看评论的时
  • STM32 HAL库 STM32CubeMX -- I2C(IIC)

    文章目录 一 I2C 协议简介I2C 物理层I2C协议层I2C架构通讯过程 二 STM32Cube MX配置三 I2C HAL库函数 一 I2C 协议简介 I2C 通讯协议 Inter xff0d Integrated Circuit 也就
  • 一个unsigned int 数的二进制表示中有多少个1

    这是一道面试题可以用以下的一些方案 第一种是很容易想到的采用循环的方式并且与1进行位与运算 xff0c 具体代码如下 1 unsigned int GetBitNumOfOne ByLoop1 unsigned int nValue 2 3
  • 网络安全(九)—— kali进行断网攻击

    kali进行断网攻击 1 查看是否有wlan0 wlan0mon网卡 ifconfig 2 开启监听 airmon ng start wlan0mon 3 扫描wifi airodump wlan0mon 攻击张书语 4 停止扫描 ctrl
  • Linux 之 System V信号量

    其实就是学几个函数的用法 xff1a ftok semget semctl semop 如果对哪个函数不熟悉就man 一下 xff0c 例如man semctl 下面是几个函数简单的实现代码 xff0c 自己可以实现一下 xff0c 助于理
  • Modern C++ 变长参数的展开

    变长参数模板和变长参数 部分 Code 来自 现代 C 43 43 教程 xff1a 高速上手 C 43 43 11 14 17 20 xff0c 这里作为笔记记录 include lt iostream gt include lt str
  • 自制计算器(C语言的简单实现)(可多次使用)

    对于刚学C语言的小白来说 xff0c 似乎感觉不到C语言可以做些什么事情而感到枯燥 xff0c 接下来我讲带大家一起来做一个小的C语言程序 计算器 在这个程序中我们使用了switch case语句 xff0c do while循环 xff0
  • 在ubuntu创建可以在图形界面登录的用户

    sudo useradd s bin bash d home wykeinstein m wykeinstein sudo passwd wykeinstein 上述两条命令创建了可以在图形界面下登录的wykeinstein用户 注销当前用
  • gitlab的部署

    1 Git Github Gitlab 的区别 Git是一个开源的分布式版本控制系统 xff0c 用于敏捷高效地处理任何或小或大的项目 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件
  • centos7上安装mysql-5.7.20版本

    一 背景环境 root 64 node1 log cat etc redhat release CentOS Linux release 7 3 1611 Core mysql的官网下载地址 二 安装步骤 1 添加mysql组和mysql用
  • 输入n个整数,查找并删除重复的数字,打印结果。

    本人为c语言初学者 xff0c 如有错误欢迎指正 在学习c语言的过程我发现到这样一个比较有意思的题目 输入n个整数 xff0c 查找并删除重复的数字 xff0c 打印结果 xff0c 所以我想分享一下我个人的解题思路 xff1a 该题可以通
  • 零基础学习数据库SQL教程(一)(简单的SELECT语句 简单的INSERT语句 简单的UPDATE语句 简单的DELETE语句)

    写在前面的话 xff1a 本文章内容是自己在LintCode网站SQL教程学习过程中做的学习总结 xff0c 以便自己复习和大家学习 xff0c 如果去刷此网站的题 xff0c 也可以把此文作为参考答案来使用 例题的答案是本人所写 xff0
  • spring源码(5)父子beans标签之间的属性关系

    一 父子beans标签之间的属性关系 回忆之前的一段代码 xff1a protected void doRegisterBeanDefinitions Element root String profileSpec 61 root getA
  • 零基础学习数据库SQL教程(二)( 比较运算符 逻辑运算符 特殊条件 ORDER BY与LIMIT)

    上接 xff1a 零基础学习数据库SQL教程 xff08 一 xff09 写在前面的话 xff1a 本文章内容是自己在LintCode网站SQL教程学习过程中做的学习总结 xff0c 以便自己复习和大家学习 xff0c 如果去刷此网站的题
  • 零基础学习数据库SQL教程(三)(算法函数 时间函数)

    上接 xff1a 零基础学习数据库SQL教程 xff08 二 xff09 写在前面的话 xff1a 本文章内容是自己在LintCode网站SQL教程学习过程中做的学习总结 xff0c 以便自己复习和大家学习 xff0c 如果去刷此网站的题
  • CCF 1021 发放奖金

    题目 xff1a 企业发放的奖金根据利润分段计算提成 当利润I低于或等于10万元的 xff0c 奖金可提10 xff1b 利润高于10万元 xff0c 低于20万元 xff0c 低于10万元的部分按10 提成 xff0c 高于10万元的部分
  • Git与Gitee、GitHub

    GitHub相当于云服务器 xff0c 这个云服务器是国外的 xff0c 为了方便国内用户需求 xff0c Github被中国化了 xff0c 变成了Gitee xff08 码 云 xff09 Github 是一个基于git实现在线代码托管
  • python ftplib使用指南

    关于服务器 这个是个难弄的东西 一台就需要几十大洋 而服务器的类型有很多种 http https tcp ftp等等 而今天说的就是使用python连接和使用ftp服务器 1 开通ftp服务器 开通局域网ftp服务器的过程就不说了 不知道的
  • python tesseract验证码识别(验证码未粘连)

    需要的库和工具及安装 其中会用到以下几个库和工具 xff1a 工具 xff1a tesseract tesseract下载地址 xff1a https digi bib uni mannheim de tesseract 1 下载适合自己版