首页 > 其他分享 >图文验证码识别

图文验证码识别

时间:2022-12-26 02:55:05浏览次数:38  
标签:imgname random 验证码 245 num im 识别 图文

对于大多数图文验证码,均可以使用开源OCR识别库进行处理,比如ddddocr,接下来以ddddocr库进行示范

一、ddddocr库安装和使用

  • 安装

    pip install ddddocr
  • 使用代码示例

    import ddddocr
    
    ocr = ddddocr.DdddOcr(old=True)
    
    with open("test.jpg", 'rb') as f:
        image = f.read()
    
    res = ocr.classification(image)
    print(res)

    old = True表示使用老版本模型,因为某些情况下老版本识别效果更佳

二、案例示范

  • 制作验证码

    import random
    import string
    from PIL import Image, ImageDraw, ImageFont
    def createCaptcha(imgname):
        '''
        生成5个字符长度的验证码
        :param imgname: 生成验证码图片名
        :return: 验证码字符串
        '''
    
        # 定义变量,用于画面的背景色、宽、高
        # bgcolor = (random.randrange(255), random.randrange(255), 100)
        bgcolor = 'white'
        width = 100
        height = 30
        # 创建画面对象
        im = Image.new('RGB', (width, height), bgcolor)
        # 创建画笔对象
        draw = ImageDraw.Draw(im)
        # 绘制50个噪点
        for i in range(50):
            point_position = (random.randrange(width), random.randrange(height))
            point_color = (random.randrange(255), random.randrange(255), random.randrange(255))
            draw.point(point_position, point_color)
        # 绘制2条干扰线
        for i in range(2):
            start_position = (random.randrange(width), random.randrange(height))
            end_position = (random.randrange(width), random.randrange(height))
            line_color = (random.randrange(255), random.randrange(255), random.randrange(255))
            draw.line([start_position, end_position], line_color)
        # 定义验证码的备选值
        str1 = string.ascii_letters + string.digits  # 大小写字母+数字共62个
        # 随机选取5个值作为验证码
        rand_str = random.sample(str1, 5)
        # 字体
        font_type = 'arial.ttf'  # 字体类型
        font_size = 20  # 字体大小
        # 构造字体对象
        font = ImageFont.truetype(font_type, font_size)
        # 构造字体颜色
        fontcolor = (random.randrange(255), random.randrange(255), random.randrange(255))
        # 绘制5个字
        for i in range(5):
            draw.text((20 * i + random.randint(1, 3), random.randint(0, 1)), rand_str[i], font=font, fill=fontcolor)
        im.save(imgname)  # 验证码内容命名图片,保存在当前目录下
        # 验证码字符串
        captcha_str = "".join(rand_str)
        return captcha_str
    View Code

    生成的验证码示例:

  • 验证码预处理

    import cv2
    
    def pre_handler(ori_imgname, new_imgname):
        '''
        图片预处理
        :param ori_imgname: 原验证码图片名
        :param new_imgname: 预处理后图片名
        :return:
        '''
    
        im = cv2.imread(ori_imgname)
        # 转灰度图像
        im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
        height, width = im.shape  # (30, 100)
    
        # 去噪线
        # opencv库中的矩阵点x, y需要反着理解
        for x in range(1, height - 1):
            for y in range(1, width - 1):
                count = 0
                if im[x, y - 1] > 245:
                    count += 1
                if im[x, y + 1] > 245:
                    count += 1
                if im[x - 1, y] > 245:
                    count += 1
                if im[x + 1, y] > 245:
                    count += 1
                if count > 2:  # 根据该点周围4个点中白点的个数,超过2个就转成白的
                    im[x, y] = 255
    
        # 去噪点
        for x in range(height):
            for y in range(width):
                # 第一排
                if x == 0:
                    # 左上角顶点
                    if y == 0:
                        num = 3
                        if im[x, y + 1] > 245:
                            num -= 1
                        if im[x + 1, y] > 245:
                            num -= 1
                        if im[x + 1, y + 1] > 245:
                            num -= 1
                    # 右上角顶点
                    elif y == width - 1:
                        num = 3
                        if im[x, y - 1] > 245:
                            num -= 1
                        if im[x + 1, y - 1] > 245:
                            num -= 1
                        if im[x + 1, y] > 245:
                            num -= 1
                    # 第一排中间点
                    else:
                        num = 5
                        if im[x, y - 1] > 245:
                            num -= 1
                        if im[x, y + 1] > 245:
                            num -= 1
                        if im[x + 1, y - 1] > 245:
                            num -= 1
                        if im[x + 1, y] > 245:
                            num -= 1
                        if im[x + 1, y + 1] > 245:
                            num -= 1
                # 最后一排
                elif x == height - 1:
                    # 左下角顶点
                    if y == 0:
                        num = 3
                        if im[x, y + 1] > 245:
                            num -= 1
                        if im[x - 1, y] > 245:
                            num -= 1
                        if im[x - 1, y + 1] > 245:
                            num -= 1
                    # 右下角顶点
                    elif y == width - 1:
                        num = 3
                        if im[x, y - 1] > 245:
                            num -= 1
                        if im[x - 1, y - 1] > 245:
                            num -= 1
                        if im[x - 1, y] > 245:
                            num -= 1
                    # 最后一排中间点
                    else:
                        num = 5
                        if im[x, y - 1] > 245:
                            num -= 1
                        if im[x, y + 1] > 245:
                            num -= 1
                        if im[x - 1, y - 1] > 245:
                            num -= 1
                        if im[x - 1, y] > 245:
                            num -= 1
                        if im[x - 1, y + 1] > 245:
                            num -= 1
                # 中间排
                else:
                    # 第一列中间点
                    if y == 0:
                        num = 5
                        if im[x - 1, y] > 245:
                            num -= 1
                        if im[x + 1, y] > 245:
                            num -= 1
                        if im[x - 1, y + 1] > 245:
                            num -= 1
                        if im[x, y + 1] > 245:
                            num -= 1
                        if im[x + 1, y + 1] > 245:
                            num -= 1
                    # 最后一列中间点
                    elif y == width - 1:
                        num = 5
                        if im[x - 1, y] > 245:
                            num -= 1
                        if im[x + 1, y] > 245:
                            num -= 1
                        if im[x - 1, y - 1] > 245:
                            num -= 1
                        if im[x, y - 1] > 245:
                            num -= 1
                        if im[x + 1, y - 1] > 245:
                            num -= 1
                    # 周围拥有8个点的点
                    else:
                        num = 8
                        if im[x - 1, y - 1] > 245:
                            num -= 1
                        if im[x - 1, y] > 245:
                            num -= 1
                        if im[x - 1, y + 1] > 245:
                            num -= 1
                        if im[x, y - 1] > 245:
                            num -= 1
                        if im[x, y + 1] > 245:
                            num -= 1
                        if im[x + 1, y - 1] > 245:
                            num -= 1
                        if im[x + 1, y] > 245:
                            num -= 1
                        if im[x + 1, y + 1] > 245:
                            num -= 1
                if num <= 1:
                    im[x, y] = 255
        cv2.imwrite(new_imgname, im)
    View Code

    如上主要进行了灰度化、去噪线、去噪点,预处理后验证码示例:

  • 验证码识别完整代码

    import cv2
    import random
    import string
    import ddddocr
    from PIL import Image, ImageDraw, ImageFont
    
    
    class CaptchaHandler:
        def main(self):
            ori_imgname = 'captcha.png'
            new_imgname = 'captcha_new.png'
            ori_str = self.createCaptcha(ori_imgname)  # 制作验证码
            self.pre_handler(ori_imgname, new_imgname)  # 图片预处理(灰度化、去噪点、去噪线)
            ocr = ddddocr.DdddOcr(old=True)
            with open(ori_imgname, 'rb') as f:
                image1 = f.read()
            res1 = ocr.classification(image1)
    
            with open(new_imgname, 'rb') as f:
                image2 = f.read()
            res2 = ocr.classification(image2)
            if ori_str.lower() == res1.lower():
                result1 = True
            else:
                result1 = False
    
            if ori_str.lower() == res2.lower():
                result2 = True
            else:
                result2 = False
    
            print(f'验证码{ori_str} 原图识别结果:{res1},处理后识别结果:{res2}')
            return result1, result2
    
        def pre_handler(self, ori_imgname, new_imgname):
            '''
            图片预处理
            :param ori_imgname: 原验证码图片名
            :param new_imgname: 预处理后图片名
            :return:
            '''
    
            im = cv2.imread(ori_imgname)
            # 转灰度图像
            im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
            height, width = im.shape  # (30, 100)
    
            # 去噪线
            # opencv库中的矩阵点x, y需要反着理解
            for x in range(1, height - 1):
                for y in range(1, width - 1):
                    count = 0
                    if im[x, y - 1] > 245:
                        count += 1
                    if im[x, y + 1] > 245:
                        count += 1
                    if im[x - 1, y] > 245:
                        count += 1
                    if im[x + 1, y] > 245:
                        count += 1
                    if count > 2:  # 根据该点周围4个点中白点的个数,超过2个就转成白的
                        im[x, y] = 255
    
            # 去噪点
            for x in range(height):
                for y in range(width):
                    # 第一排
                    if x == 0:
                        # 左上角顶点
                        if y == 0:
                            num = 3
                            if im[x, y + 1] > 245:
                                num -= 1
                            if im[x + 1, y] > 245:
                                num -= 1
                            if im[x + 1, y + 1] > 245:
                                num -= 1
                        # 右上角顶点
                        elif y == width - 1:
                            num = 3
                            if im[x, y - 1] > 245:
                                num -= 1
                            if im[x + 1, y - 1] > 245:
                                num -= 1
                            if im[x + 1, y] > 245:
                                num -= 1
                        # 第一排中间点
                        else:
                            num = 5
                            if im[x, y - 1] > 245:
                                num -= 1
                            if im[x, y + 1] > 245:
                                num -= 1
                            if im[x + 1, y - 1] > 245:
                                num -= 1
                            if im[x + 1, y] > 245:
                                num -= 1
                            if im[x + 1, y + 1] > 245:
                                num -= 1
                    # 最后一排
                    elif x == height - 1:
                        # 左下角顶点
                        if y == 0:
                            num = 3
                            if im[x, y + 1] > 245:
                                num -= 1
                            if im[x - 1, y] > 245:
                                num -= 1
                            if im[x - 1, y + 1] > 245:
                                num -= 1
                        # 右下角顶点
                        elif y == width - 1:
                            num = 3
                            if im[x, y - 1] > 245:
                                num -= 1
                            if im[x - 1, y - 1] > 245:
                                num -= 1
                            if im[x - 1, y] > 245:
                                num -= 1
                        # 最后一排中间点
                        else:
                            num = 5
                            if im[x, y - 1] > 245:
                                num -= 1
                            if im[x, y + 1] > 245:
                                num -= 1
                            if im[x - 1, y - 1] > 245:
                                num -= 1
                            if im[x - 1, y] > 245:
                                num -= 1
                            if im[x - 1, y + 1] > 245:
                                num -= 1
                    # 中间排
                    else:
                        # 第一列中间点
                        if y == 0:
                            num = 5
                            if im[x - 1, y] > 245:
                                num -= 1
                            if im[x + 1, y] > 245:
                                num -= 1
                            if im[x - 1, y + 1] > 245:
                                num -= 1
                            if im[x, y + 1] > 245:
                                num -= 1
                            if im[x + 1, y + 1] > 245:
                                num -= 1
                        # 最后一列中间点
                        elif y == width - 1:
                            num = 5
                            if im[x - 1, y] > 245:
                                num -= 1
                            if im[x + 1, y] > 245:
                                num -= 1
                            if im[x - 1, y - 1] > 245:
                                num -= 1
                            if im[x, y - 1] > 245:
                                num -= 1
                            if im[x + 1, y - 1] > 245:
                                num -= 1
                        # 周围拥有8个点的点
                        else:
                            num = 8
                            if im[x - 1, y - 1] > 245:
                                num -= 1
                            if im[x - 1, y] > 245:
                                num -= 1
                            if im[x - 1, y + 1] > 245:
                                num -= 1
                            if im[x, y - 1] > 245:
                                num -= 1
                            if im[x, y + 1] > 245:
                                num -= 1
                            if im[x + 1, y - 1] > 245:
                                num -= 1
                            if im[x + 1, y] > 245:
                                num -= 1
                            if im[x + 1, y + 1] > 245:
                                num -= 1
                    if num <= 1:
                        im[x, y] = 255
            cv2.imwrite(new_imgname, im)
    
        def createCaptcha(self, imgname):
            '''
            生成5个字符长度的验证码
            :param imgname: 生成验证码图片名
            :return: 验证码字符串
            '''
    
            # 定义变量,用于画面的背景色、宽、高
            # bgcolor = (random.randrange(255), random.randrange(255), 100)
            bgcolor = 'white'
            width = 100
            height = 30
            # 创建画面对象
            im = Image.new('RGB', (width, height), bgcolor)
            # 创建画笔对象
            draw = ImageDraw.Draw(im)
            # 绘制50个噪点
            for i in range(50):
                point_position = (random.randrange(width), random.randrange(height))
                point_color = (random.randrange(255), random.randrange(255), random.randrange(255))
                draw.point(point_position, point_color)
            # 绘制2条干扰线
            for i in range(2):
                start_position = (random.randrange(width), random.randrange(height))
                end_position = (random.randrange(width), random.randrange(height))
                line_color = (random.randrange(255), random.randrange(255), random.randrange(255))
                draw.line([start_position, end_position], line_color)
            # 定义验证码的备选值
            str1 = string.ascii_letters + string.digits  # 大小写字母+数字共62个
            # 随机选取5个值作为验证码
            rand_str = random.sample(str1, 5)
            # 字体
            font_type = 'arial.ttf'  # 字体类型
            font_size = 20  # 字体大小
            # 构造字体对象
            font = ImageFont.truetype(font_type, font_size)
            # 构造字体颜色
            fontcolor = (random.randrange(255), random.randrange(255), random.randrange(255))
            # 绘制5个字
            for i in range(5):
                draw.text((20 * i + random.randint(1, 3), random.randint(0, 1)), rand_str[i], font=font, fill=fontcolor)
            im.save(imgname)  # 验证码内容命名图片,保存在当前目录下
            # 验证码字符串
            captcha_str = "".join(rand_str)
            return captcha_str
    
    
    if __name__ == '__main__':
        handler = CaptchaHandler()
        count1 = 0
        count2 = 0
        for i in range(200):
            result1, result2 = handler.main()
            if result1 is True:
                count1 += 1
            if result2 is True:
                count2 += 1
        print(f'识别200次,原图成功{count1}次,预处理后成功{count2}次')
    View Code

    通过200次测试,在忽略字符大小写的情况下,ddddocr库识别原图和经过预处理后验证码的成功率都很高,接近90%的成功率

标签:imgname,random,验证码,245,num,im,识别,图文
From: https://www.cnblogs.com/eliwang/p/17004910.html

相关文章

  • 基于LSTM网络的视觉识别研究与实现——简化版
    1.问题描述:以人脸图像的视觉识别为研究对象,研究了基于LSTM长短期记忆单元网络的视觉识别算法,通过使用卷积神经网络学习人脸图像的特征信息,然后使用LSTM网络建立序列知识,......
  • 精通visual c++指纹模式识别系统算法及实现
    通过学习,掌握以下几个问题:1、核心算法,并且向GVF衍生;2、核心库封装的方法2016年11月16日06:52:51昨日实现了梯度场和频率场的计算。最大的感觉就是建立基础代码库的重要性。......
  • 页面调整、登录功能_验证码显示、代码实现
    页面调整会做出以下的功能列表查询,登录,添加,删除,修改删除选中,分页查询,复杂条件查询 <%@pagecontentType="text/html;charset=UTF-8"language="j......
  • 【模式识别】判别函数和感知机算法
    给定两个类别的一共8个样本,通过感知机算法求解判别函数defbi_perception():X1=np.array([[0,0,0],[1,0,0],[1,0,1],......
  • 如何生成excel文件作为图像识别结果
    如何生成excel文件作为图像识别结果在进行大规模图像处理的时候,如果能够以表格的形式生成结果文件,将非常的直观。这个时候,选择excel作为结果输出文件,将是合适的。......
  • 【验证码逆向专栏】某验三代滑块验证码逆向分析
    声明本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!本......
  • 【验证码逆向专栏】某片滑块、点选验证码逆向分析
    声明本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果......
  • 答题卡图像识别项目
    答题卡图像识别需求分析、市场分析和技术实现  P.S博客发布以来,获得多方的关注。相关内容我已经以教程的形式进行了整理发布(包括算法、硬件搭建和软件框架),如果需要请移步......
  • 机器学习—车辆种类图片识别
    机器学习—车辆种类图片识别一、选题的背景    随着城市化建设不断发展,我国对交通建设的需求也不断增长,成为了世界上在交通领域基础设施建设最快的国家之一,但车辆......
  • 图文并茂解释TCPIP 3次握手4次挥手
    1.TCP与UDP的区别TCP(TransmissionControlProtocol,传输控制协议)是面向连接的,可靠的通信协议,而UDP(UserDatagramProtocol,用户数据报协议)是无连接的,不可靠的通信协议......