基于防止ddddocr通过对图像膨胀腐蚀操作进行识别

文章介绍了如何使用Python的ddddocr库进行验证码识别,以及如何通过图形学的腐蚀和膨胀操作来对抗OCR识别。通过创建带有相同颜色噪点的验证码,可以降低OCR的识别成功率。此外,文章提供了生成具有干扰噪点的验证码图片的代码示例,并展示了添加噪点后对识别率的影响。
摘要由CSDN通过智能技术生成

在python存在一个比较好用的简单验证码识别库ddddocr

import ddddocr

# 需要识别图片的路径
with open("captcha.jpg", 'rb') as f:
    img_bytes = f.read()
res = ocr.classification(img_bytes)

print(res) # 识别后的结果

这种操作简单,易上手,是各大爬虫编写者的利器

有识别就有反识别,这里提供一种操作用于反ddddocr的识别

我们先了解图形学中膨胀和腐蚀是什么

图形学之腐蚀膨胀https://blog.csdn.net/u011028345/article/details/76152243?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169013324416800215033996%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=169013324416800215033996&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-76152243-null-null.142%5Ev90%5Echatsearch,239%5Ev3%5Econtrol&utm_term=%E5%9B%BE%E5%BD%A2%E5%AD%A6%E8%86%A8%E8%83%80&spm=1018.2226.3001.4187

归根到底,膨胀就是把细节放大,腐蚀就是把细节忽略

0 0 0 0 0 0 0 0 0 0              0 0 0 0 0 0 0 0 0 0 
0 1 0 0 0 0 0 0 0 0              0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0              0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0              0 0 0 0 0 0 0 0 0 0 
0 0 0 0 1 0 0 0 0 0      ->      0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0              0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0              0 0 0 0 0 0 0 0 0 0 
0 1 0 0 0 0 0 1 0 0              0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0              0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0              0 0 0 0 0 0 0 0 0 0 

(把单独零散的1去除了)

这种操作便是针对验证码图片中的噪点,通过腐蚀操作减少噪点的出现

而在许多ocr中,会采取一种叫闭运算的操作,即腐蚀后膨胀,这样不仅能减少干扰,还能扩大重要的识别轮廓

我们从闭运算下手突破

问:为什么我们的噪点会被消除?

答:噪点比例(噪点的大小 / 字符的粗细)不够大

在ocr中,一般会通过图片的比例进行一定程度的闭运算,为了消除噪点而保留原有的字符,就会寻找一个合适程度使得可以消除噪点且保留字符

问:我们是否可以通过一种方法,使得噪点和字符同时存在呢?

答:可以,把噪点大小设置为字符粗细即可

通过这种方式,ocr就无法找到一种方法使得可以消除噪点且保留字符,噪点和字符同时存在

显然,这种方法还不足够,许多ocr已经具有对颜色的敏感识别,不再是一味的转为灰度图再识别

我们在此基础上,设置噪点颜色与字符颜色相同

使用pillow库

# 生成验证码图片
from PIL import Image, ImageDraw, ImageFont
import random, ddddocr

# 字符组
# 有些字母或数字比较具有迷惑性,比如:L I l 1 i O o 0,这里进行了排除
chars = "ABCDEFHJKLMNPQRSTUVXYZ23456789"

# ddddocr识别
ocr = ddddocr.DdddOcr()

# 生成验证码
def generate_code(length):
    # 随机取出
    char_list = random.choices(chars, k=length)
    code = "".join(char_list)
    return code


# 随机生成颜色
def get_color(min_value=0, max_value=255):
    return (
        random.randint(min_value, max_value),
        random.randint(min_value, max_value),
        random.randint(min_value, max_value)
    )


def main(width=120, height=50, code_length=4):
    """
    width,height为生成图片的宽高
    code_length为生成验证码的长度
    """
    # 新建一个图像对象
    image = Image.new(
        'RGB',
        (width, height),
        get_color(64, 255) # 使用一个比较明亮的颜色作为背景
    )
    # 设置字体和字号
    font = ImageFont.truetype("C:\\Windows\\Fonts\\arial.ttf", size=40)
    draw = ImageDraw.Draw(image)
    # 获取一个随机验证码
    text = generate_code(code_length)
    # 获取字符串的宽度和高度
    bbox = draw.textbbox(xy=(width, height), text=text, font=font)
    text_width = bbox[2] - bbox[0]
    text_heigtht = bbox[3] - bbox[1]
    # 绘画验证码的起始位置(居中)
    offset_x = (width - text_width) // 2
    offset_y = (height - text_heigtht) // 2
    # 每个字符的间隔
    width_gap = text_width // code_length
    # 对每个字符操作
    for char in text:
        # 生成一个比较暗的颜色
        color = get_color(0, 64)
        draw.text(
            xy=(
                # 每个字符的随机偏移量
                offset_x + random.randint(-4, 4),
                offset_y + random.randint(-4, 4)
            ),
            text=char,
            font=font,
            fill=color
        )
        # 绘制干扰噪点像素 概率是0.025,可以自行更改
        for j in range(int(width * height * 0.025)):
            # 生成噪点的随机位置
            pos_x, pos_y = random.randint(0, width), random.randint(0, height)
            draw.rectangle(
                # 噪点的大小,这里需要根据字符的粗细来调整
                (pos_x, pos_y, pos_x + random.randint(0, 3), pos_y + random.randint(0, 3)),
                # 这里一定要使用与字符相同的颜色
                fill=color
            )
        # 下一个字符的位置
        offset_x += width_gap
    res = ocr.classification(image)
    # 一般验证码对大小写不敏感
    print("your's code:", text.lower())
    print("ocr's result:", res.lower())
    # 展示图像
    image.show()

if __name__ == "__main__":
    main()

如果代码出现:

AttributeError: module 'PIL.Image' has no attribute 'ANTIALIAS'

解决方案:

解决ddddocr AttributeError: module ‘PIL.Image‘ has no attribute ‘ANTIALIAS‘报错

可以见到,迷惑性还是很强的,而且图像也很清楚

 测试识别成功率,把代码更改为

    # 一般验证码对大小写不敏感
    # print("your's code:", text.lower())
    # print("ocr's result:", res.lower())
    # 展示图像
    # image.show()
    #
    return res.lower() == text.lower()


if __name__ == "__main__":
    total = 10000
    couter = 0
    for i in range(total):
        print("NO.",i)
        if main():
            couter += 1
    print(couter*100/total,"%")

不添加噪点

97.36 %

添加噪点后

2.11 %

有了大幅度提升

之后再更新其他迷惑操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值