• mac使用python识别图形验证码


    前言

    • 最近在研究验证码相关的操作,所以准备记录下安装以及使用的过程。虽然之前对验证码的破解有所了解的,但是之前都是简单使用之后就不用了,没有记录一个详细的过程,所以后面再用起来也要重新从网上查找资料比较麻烦,所以这里准备对研究过程的关键点做一个记录。

    首先这篇文章,主要是研究图形验证码,后期会不定时拓展内容。

    在网上查了很多版本的图形验证码识别,目前看到最多的两个模块是pytesseract和tesserocr,但是因为我这里安装tesserocr的时候各种出错,所以最终我锁定了使用pytesseract。
    那么接下来,就记录下安装以及使用过程。这里的系统环境是mac os 10.14.

    安装tesserocr

    brew install tesserocr
    

    因为pytesseract依赖于tesserocr所以首先需要先安装tesserocr这个软件。接下来就是安装python相关的包

    安装python所需要的包

    pip3 install pytesseract
    pip3 install pillow 
    

    安装pytesseract是ocr识别图片上的字,因为验证码的识别难度高低不同,所以在这个过程中需要对图片做一定的处理,这就需要使用处理图片的模块pillow。

    一个简单的demo

    import pytesseract
    from PIL import Image
    import os
    
    
    def binarizing(img, threshold):
        """传入image对象进行灰度、二值处理"""
        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
    
    
    _temp = os.path.dirname(__file__)
    file_path = os.path.join(_temp, 'code2.jpg')
    print("file_path", file_path)
    image = Image.open(file_path)
    image = image.convert('L')
    threshold = 157
    table = []
    # 接下来是二值化处理
    # 遍历所有像素,大于阈值的为黑色,threshold是阀值
    image = binarizing(image, threshold)
    result = pytesseract.image_to_string(image)
    print(result)
    

    示例中的图片

    需要用到的图像知识:

    对于彩色图像,不管其图像格式是PNG,还是BMP,或者JPG,在PIL中,使用Image模块的open()函数打开后,返回的图像对象的模式都是“RGB”。而对于灰度图像,不管其图像格式是PNG,还是BMP,或者JPG,打开后,其模式为“L”也就是我们说的灰度化的一个操作。除此之外,还有其他的模式,不过我们在处理验证码的时候是将其转为灰度模式,所以就不强调其他的模式了。

    模式“L”

    模式“L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。在PIL中,从模式“RGB”转换为“L”模式是按照下面的公式转换的:

    L = R * 299/1000 + G * 587/1000+ B * 114/1000
    

    通过灰度化之后的图片变为

    灰度化我们还要对其进行二值化操作

    二值化操作

    二值化故名思议,就是整个图像所有像素只有两个值可以选择,一个是黑(灰度为0),一个是白(灰度为255)。二值化的好处就是将图片上的有用信息和无用信息区分开来,比如二值化之后的验证码图片,验证码像素为黑色,背景和干扰点为白色,这样后面对验证码像素处理的时候就会很方便。对于简单的图形验证码,到这里基本上就够了,但是如果有干扰线,还要进行除干扰线的操作。
    对应的代码为

    def binarizing(img, threshold):
        """传入image对象进行灰度、二值处理"""
        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 #小于阀值设为0,0是黑色
                else:
                    pixdata[x, y] = 255 0 #大于阀值设为255,255是白色
        return img
    
    

    此时的图片效果为

    可以看到图片变得锐化了很多,这个时候再去识别就比较好识别了。

    去干扰线

    常见的4邻域、8邻域算法。所谓的X邻域算法,可以参考手机九宫格输入法,按键5为要判断的像素点,4邻域就是判断上下左右,8邻域就是判断周围8个像素点。如果这4或8个点中255的个数大于某个阈值则判断这个点为噪音,阈值可以根据实际情况修改。

    使用cv2处理

    除此之外还可以使用cv2模块进行处理。
    安装

     pip install opencv-python
    

    代码示例

    # -*- coding: utf-8 -*-
    # @时间 : 2020-01-08 18:01
    # @作者 : 陈祥安
    # @文件名 : cv2_demo.py
    # @公众号: Python学习开发
    
    import cv2
    import numpy as np
    import os
    
    _temp = os.path.dirname(__file__)
    file_path = os.path.join(_temp, 'code2.jpg')
    
    
    def remove_noise(img, k=4):
        ###8领域过滤
        img2 = img.copy()
    
        #   img处理数据,k过滤条件
        w, h = img2.shape
    
        def get_neighbors(img3, r, c):
            count = 0
            for i in [r - 1, r, r + 1]:
                for j in [c - 1, c, c + 1]:
                    if img3[i, j] > 10:  # 纯白色
                        count += 1
            return count
    
        #   两层for循环判断所有的点
        for x in range(w):
            for y in range(h):
                if x == 0 or y == 0 or x == w - 1 or y == h - 1:
                    img2[x, y] = 255
                else:
                    n = get_neighbors(img2, x, y)  # 获取邻居数量,纯白色的邻居
                    if n > k:
                        img2[x, y] = 255
        return img2
    
    
    img = cv2.imread(file_path)
    
    # 将图片灰度化处理,降维,加权进行灰度化c
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    t, gray2 = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)
    cv2.imshow('threshold', gray2)
    result = remove_noise(gray2)
    cv2.imshow('8neighbors', result)
    
    cv2.waitKey(0)
    
    #cv2.destroyAllWindows()
    

    参考资料

    https://www.jb51.net/article/141428.htm
    https://blog.csdn.net/icamera0/article/details/50843172
    https://www.jb51.net/article/174093.htm

  • 相关阅读:
    20172311-ASL测试 2018-1938872补充博客
    20172311《程序设计与数据结构》第四周学习总结
    20172311 实验一《程序设计与数据结构》线性结构 实验报告
    20172311《程序设计与数据结构》第三周学习总结
    20172311《程序设计与数据结构》第二周学习总结
    20172311《程序设计与数据结构》第一周学习总结
    20172311 《程序设计与数据结构》(上)课程总结
    20172311 2017-2018-2 《程序设计与数据结构》实验五报告
    20172311 2017-2018-2 《程序设计与数据结构》第十一周学习总结
    20172323 2018-2019-1 《程序设计与数据结构》课堂作业报告
  • 原文地址:https://www.cnblogs.com/c-x-a/p/12168010.html
Copyright © 2020-2023  润新知