• python之pillow模块学习--验证码的生成和破解


    一、基础学习

    在Python中,有一个优秀的图像处理框架,就是PIL库,pip install pillow

    示例1

    from PIL import Image
    
    # 读取当前图片
    im = Image.open('test.png')
    
    # 用系统自带的图片查看器查看该图片
    im.show()
    
    # 将图片进行逆时针旋转
    im.rotate(90).show()
    
    # 将图片进行顺时针旋转
    im.rotate(-90).show()
    
    # 保存图像为gif格式
    im.save("save.gif", "GIF")
    
    # resize成128*128像素大小
    out = im.resize((128, 128))
    out.save("test2.png", "png")
    
    # 拷贝黏贴:设置要拷贝的地区的大小,里面含有四个元素,为左上右下
    box = (100, 100, 200, 200)
    region = im.crop(box) # 按照box的大小拷贝到region里面
    region.save("corp.png", "png")
    
    # 获取图片基本信息
    # format: 图片格式;size:图片大小(长*宽); mode: 色彩模式
    print(im.format, im.size, im.mode)
    
    # 等比例缩放
    size = (128, 128)
    im.thumbnail(size, Image.ANTIALIAS)
    im.save("new.png", "png")
    
    # 通道分离,将图片封装成三个或四个通道,分别为三个或四个图像对象
    print(im.mode)  # 查看图片是什么色彩模式
    r, g, b, a = im.split()  # 我这里是RBGA模式
    # r, g, b = im.split()  # 如果是RGB模式
    
    # 能分离就能合并,将b,r两个通道进行翻转。
    im = Image.merge("RGBA", (b, g, r, a))  # Image.merge("RGB", (b, g, r))
    
    # 图像左右转换
    im.transpose(Image.FLIP_LEFT_RIGHT).show()
    
    # 图像上下转换
    im.transpose(Image.FLIP_TOP_BOTTOM).show()
    
    # 图像类型转换
    im = im.convert("RGB")
    im.show()
    im = im.convert("L")  # 灰度图
    im.show()

    二、生成验证码

    生成图片验证码

    import random
    from PIL import Image, ImageDraw, ImageFont, ImageFilter
    
    """图片模糊化处理
    im = Image.open('test.png')
    # BLUR:模糊  还有:CONTOUR DETAIL等等
    im2 = im.filter(ImageFilter.BLUR)
    im2.show()
    """
    
    
    # 返回随机的RGB数字
    def random_color():
        return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
    
    
    def get_code():
        with open('1.png', 'wb') as f:
            # 第一步:生成一张图片(画布)
            # 创建一个随机颜色的图片对象
            # 参数:颜色模式,图片大小,图片颜色
            img_obj = Image.new('RGB', (250, 35), random_color())
    
            # 第二步:在该图片对象上生成一个画笔对象
            draw_obj = ImageDraw.Draw(img_obj)
    
            # 使用什么字体,字体大小,kumo.ttf是我本地下载好的字体文件(sc.chinaz.com)可下载
            font_obj = ImageFont.truetype('static/font/kumo.ttf', 28)
    
            # 生成验证码
            code = ''
            for i in range(6):
                num = str(random.randint(0, 9))  # 数字
                lower = chr(random.randint(97, 122))  # 小写字母
                upper = chr(random.randint(65, 90))  # 大写字母
                c = random.choice([num, lower, upper])  # 随机选取一个
                code += str(c)
    
                # 用画笔把验证码画到图片上
                # 参数:xy:坐标,画在哪个位置;text:画的内容;fill:画什么颜色;font:字体格式
                draw_obj.text((35 + i * 30, 0), c, fill=random_color(), font=font_obj)
            # 保存图片并模糊化
            image = img_obj.filter(ImageFilter.BLUR)
            image.save(f)
    
    
    get_code()

    加干扰线和干扰点

    画完验证码后,可以添加一些干扰
    就是在 draw_obj.text((35 + i*30, 0), c, fill=random_color(), font=font_obj)之后加
    
    1. 加干扰线
    width = 250  # 图片宽度(防止越界)
    height = 35
    for i in range(5):
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, height)
        y2 = random.randint(0, height)
        draw_obj.line((x1, y1, x2, y2), fill=random_color())
    
    2. 加干扰点
    for i in range(40):
        draw_obj.point([random.randint(0, width), random.randint(0, height)], fill=random_color())
        x = random.randint(0, width)
        y = random.randint(0, height)
        draw_obj.arc((x, y, x+4, y+4), 0, 90, fill=random_color())

    三、验证码破解

    1、预备知识

    二值化

    from PIL import Image
    
    """
    灰度图像上每个像素的颜色值又称为灰度,指黑白图像中点的颜色深度,
    范围一般从0到255,白色为255,黑色为0。所谓灰度值是指色彩的浓淡程度,
    灰度直方图是指一幅数字图像中,对应每一个灰度值统计出具有该灰度值的象素数。
    """
    
    # 方法一:使用load函数获取到图片像素,直接对像素进行修改
    def convert_img(img, threshold):
        # 模式L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度
        img = img.convert("L")  # img.convert("1")也是可以直接二值化,但是阈值是固定的127
        # 图片的像素二维数组,例如:pixels[0,0] 第一行第一个的像素值
        pixels = img.load()
        # 二值化:自定义灰度界限,大于这个值为白色,小于这个值为黑色
        for x in range(img.width):
            for y in range(img.height):
                if pixels[x, y] > threshold:
                    pixels[x, y] = 255
                else:
                    pixels[x, y] = 0
        return img
    
    
    # 方法二:使用point函数
    from PIL import Image
    
    
    img = Image.open("captcha.png")
    # 模式L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。
    Img = img.convert('L')
    # 自定义灰度界限,大于这个值为白色,小于这个值为黑色
    threshold = 140
    table = []
    
    for i in range(256):
        if i < threshold:
            table.append(0)
        else:
            table.append(1)
    
    # 图片二值化
    photo = Img.point(table, '1')
    photo.save("test2.jpg")

    获取每个像素点的RGB(RGBA)值

    我的理解是:像素值是由这个点的RGB(A)值结合得到的,因此注意了,上面的像素值,我们这里是RGB值

    # 获取每个像素点的RGB(RGBA)值
    from PIL import Image
    
    
    im = Image.open("captcha.png")
    # getdata()函数的返回值是一个sequence对象,
    # sequence对象的每一个值就是这个像素点对应的R、G、B(A)值
    data = im.getdata()
    data = list(data)
    print(data)  # [(135, 142, 169, 255), (104, 111, 139, 255), ....]

    2、利用Tesseract识别图片验证码

    Tesseract是一个开源的OCR(Optical Character Recognition,光学字符识别)引擎,可以识别多种格式的图像文件并将其转换成文本,目前已支持60多种语言(包括中文)。 Tesseract最初由HP公司开发,后来由Google维护。

    因此,我们需要在自己的环境安装Tesseract,至于怎么安装,百度下吧。。。

    然后再下载 python对应的Tesseract模块

    pip install pytesseract
    from PIL import Image
    import pytesseract
    
    """
    灰度图像上每个像素的颜色值又称为灰度,指黑白图像中点的颜色深度,
    范围一般从0到255,白色为255,黑色为0。所谓灰度值是指色彩的浓淡程度,
    灰度直方图是指一幅数字图像中,对应每一个灰度值统计出具有该灰度值的象素数。
    """
    
    
    def convert_img(img, threshold):
        """图片二值化"""
        # 模式L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度
        img = img.convert("L")  # img.convert("1")也是可以直接二值化,但是阈值是固定的127
        # 图片的像素二维数组,例如:pixels[0,0] 第一行第一个的像素值
        pixels = img.load()
        # 二值化:自定义灰度界限,大于这个值为白色,小于这个值为黑色
        for x in range(img.width):
            for y in range(img.height):
                if pixels[x, y] > threshold:
                    pixels[x, y] = 255
                else:
                    pixels[x, y] = 0
        return img
    
    
    def denoise(img):
        """图片降噪"""
        data = img.getdata()
        w, h = img.size
        count = 0
        for x in range(1, h - 1):
            for y in range(1, h - 1):
                # 找出各个像素方向
                mid_pixel = data[w * y + x]
                if mid_pixel == 0:
                    top_pixel = data[w * (y - 1) + x]
                    left_pixel = data[w * y + (x - 1)]
                    down_pixel = data[w * (y + 1) + x]
                    right_pixel = data[w * y + (x + 1)]
    
                    if top_pixel == 0:
                        count += 1
                    if left_pixel == 0:
                        count += 1
                    if down_pixel == 0:
                        count += 1
                    if right_pixel == 0:
                        count += 1
                    if count > 4:
                        img.putpixel((x, y), 0)
        return img
    
    
    if __name__ == '__main__':
        captcha = Image.open("captcha.png")
    
        res = convert_img(captcha, 140)
        ret = denoise(res)
        ret.show()
        result = pytesseract.image_to_string(ret)
        print(result)

    3、Tesseract-OCR样本训练

    待我研究研究。。。

  • 相关阅读:
    最长公共子序列算法问题代码(使用JavaScript实现)
    硬币找零问题算法几种不同的代码实现方式(使用Python实现)
    基数排序(使用Python实现)
    桶排序(使用Python实现)
    减法要用 signed 型
    16系列和18系列的不同
    Proteus中常用元器件名字
    数值类型
    PIC单片机之时钟设置
    MOS管使PIC单片机不能正常运行
  • 原文地址:https://www.cnblogs.com/Zzbj/p/13797672.html
Copyright © 2020-2023  润新知