zoukankan      html  css  js  c++  java
  • 图像处理技巧

    验证码大多是数字、字母的组合,国内也有使用汉字的。在这个基础上增加噪点、干扰线、变形、重叠、

    不同字体颜色等方法来增加识别难度。

    相应的,验证码识别大体可以分为下面几个步骤

    1. 灰度处理

    2. 增加对比度(可选)

    3. 二值化

    4. 降噪

    5. 倾斜校正分割字符

    6. 建立训练库

    7. 识别


    灰度化

    ​ 像素点是最小的图像单元,一张图片由好多的像素点构成, 一个像素点的颜色是由RGB三个值来表现的,

    所以一个像素点矩阵对应三个颜色向量矩阵,我们对图像的处理就是对这个像素点矩阵的操作,

    想要改变某个像素点的颜色,只要在这个像素点矩阵中找到这个像素点的位置(x, y),

    因为一个像素点的颜色由红、绿、蓝三个颜色变量表示,所以我们通过给这三个变量赋值,来改变这个像素点的颜色.

    图片的灰度化,就是让像素点矩阵中的每一个像素点都满足下面的关系:R=G=B,此时的这个值叫做灰度值.

    灰度化的转化公式一般为:

    R = G = B = 处理前的 R*0.3 + G*0.59 + B*0.11

    img = img.convert('L')  #转为灰度图

     

    二值化

    二值化就是让图像的像素点矩阵中的每个像素点的灰度值为0(黑)或者255(白) ,从而实现二值化,

    让整个图像呈现只有黑和白的效果。

    原理是利用设定的一个阈值来判断图像像素为0还是255,小于阈值的变为0(黑色), 大于的变为255(白色)。

    这个临界灰度值就被称为阈值,阈值的设置很重要。阈值过大或过小都会对图片造成损坏。

    选择阈值的原则是:既要尽可能保存图像信息,又要尽可能减少背景和噪声的干扰,

    常用方法

    • 取阈值为127(0~255的中数,(0+255)/2=127 )

      好处是计算量小速度快,

      缺点也是很明显的 ,对于图片中内容色彩分布较大的图片,很容易造成内容的缺失。

    • 平均值法

      计算像素点矩阵中的所有像素点的灰度值的平均值avg

      (像素点1灰度值+...+像素点n灰度值)/ n = 像素点平均值avg

      这样做比方法1好一些。 但可能导致部分对象像素或者背景像素丢失。

    def averageThreshold(img):
        pixdata = img.load()
        width,height = img.size
        
        threshold = sum(img.getdata())/(width*height)   #计算图片的平均阈值
    # 遍历所有像素,大于阈值的为白色
        for y in range(height):
            for x in range(width):
                if pixdata[x, y] < threshold:
                    pixdata[x, y] = 0
                else:
                    pixdata[x,y] = 255return img
    • 双峰法

      图像由前景和背景组成,在灰度直方图上,前后二景都形成高峰,在双峰之间的最低谷处就是图像的阈值所在。

    • 当前后景的对比较为强烈时,分割效果较好;否则基本无效。

    • 迭代法

      首先选择一个近似阈值作为估计值的初始值,然后进行分割,产生子图像,并根据子图像的特性来选取新的阈值,

      再利用新的阈值分割图像,经过几次循环,使错误分割的图像像素点降到最少。这样做的效果好于用初始阈值直接分割图像的效果。

      1. 求出图象的最大灰度值和最小灰度值,分别记为Pmax和Pmin,令初始阈值T0=(Pmax+Pmin)/2

      2. 根据阈值TK将图象分割为前景和背景,(小于 T0 的像素部分,大于T0的背景部分),并分别求其均值 avgPix, avgBac

      3. 求出新阈值TK = ( avgPix+avgBac) / 2;

      4. 若T0=TK,则所得即为阈值;否则转2,迭代计算 。

        from PIL import Image
        ​
        def iterGetThreshold(img, pixdata, width, height):
            pixPrs = pixBac = []                     #用于统计前景和背景平均阈值
            threshold = 0
            pixel_min, pixel_max = img.getextrema()  # 获得图片中最大和最小灰度值
            newThreshold = int((pixel_min + pixel_max) / 2)  # 初始阈值
        while True:
                if abs(threshold -  newThreshold) < 5:   #差值小于5,退出
                    break
                for y in range(height):
                    for x in range(width):
                        if pixdata[x, y] >= newThreshold:
                            pixBac.append(pixdata[x,y])    #大于阈值 为背景
                        else:
                            pixPrs.append(pixdata[x,y])    #小于, 前景
        ​
                avgPrs = sum(pixPrs)/len(pixPrs)
                avgBac = sum(pixBac)/len(pixBac)
                threshold = newThreshold
                newThreshold = int((avgPrs+avgBac)/2)
        ​
            return newThreshold
        ​
        ​
        def binary(img, threshold=None):
            img = img.convert('L')  #转为灰度图
            pixdata = img.load()
            width, height = img.size
        ​
            if not threshold:
                threshold = iterGetThreshold(img, pixdata,width, height)
            # 遍历所有像素,大于阈值的为白色
            for y in range(height):
                for x in range(width):
                    if pixdata[x, y] < threshold:
                        pixdata[x, y] = 0
                    else:
                        pixdata[x,y] = 255return img
        ​
        img = Image.open('test-1.jpg')
        img.show()
        new_img = Binary(img)new_img.show()

    2. 降噪

    ​ 从前面经过二值化处理,如果一个像素点是图片或者干扰因素的一部分,那么它的灰度值一定是0,

    即黑色; 如果一个点是背景,则其灰度值应该是255,白色。

    ​ 因此对于孤立的噪点,其周围应该都是白色,或者大多数点都是白色pixel

    ​ 如果图片分辨率够高,一个噪点实际上可能是有很多个点组成 ,所以此时的判断条件应该放宽,

    即一个点是黑色的并且相邻的8个点为白色点的个数大于一个固定值,那么这个点就是噪点 。

    ​ 常见的4邻域、8邻域算法。所谓的X邻域算法,可以参考手机九宫格输入法,按键5为要判断的像素点,

    4邻域就是判断上下左右,8邻域就是判断周围8个像素点。如果这4或8个点中255的个数大于某个阈值则判断这个点为噪音,

    阈值可以根据实际情况修改。

    ​ 这个方法对小噪点比较好,如果阀值设的比较大,很多验证码字符也会受到很大影响,

    因为验证码可能就是一些断断续续的点连出来的,阀值设太大,尽管噪点没了,验证码也会没了。

    def depoint(img, N=2):
        pixdata = img.load()
        width, height = img.size
        for y in range(1, height - 1):
            for x in range(1, width - 1):
                count = 0
                if pixdata[x, y - 1] == 255:  #
                    count = count + 1
                if pixdata[x, y + 1] == 255:  #
                    count = count + 1
                if pixdata[x - 1, y] == 255:  #
                    count = count + 1
                if pixdata[x + 1, y] == 255:  #
                    count = count + 1# if pixdata[x-1, y-1] == 255:  #左上
                #     count = count + 1
                # if pixdata[x+1, y-1] == 255:  #右上
                #     count = count + 1
                # if pixdata[x-1, y+1] == 255:  #左下
                #     count = count + 1
                # if pixdata[x+1, y+1] == 255:  #右下
                #     count = count + 1
    if count > N:
                    pixdata[x, y] = 255  #设置为白色
        return img
    ​
    depoint(img).show()
    
     

    OCR (Optical Character Recognition)光学字符识别, 指的是对文本资料的图像文件进行分析识别处理,获取文集及版面信息的过程

    Tesseract-OCR是一个开源的字符识别引擎,我们可以用他来识别一些简单的验证码。

    Windows安装:
    安装文件点击下载
    Linux安装:
    sudo apt-get install tesseract-ocr
    sudo apt-get install libtesseract-dev
    Mac安装:
    brew install tesseract

    Pytesser3是一个在Python内使用Tesseract-Ocr的库,安装非常简单:
    pip install Pytesser3

    然后需要进行配置, 将pytesser3包下面__init__文件内tesseract_exe_name的值设置为为你的tesseract.exe的路径

    使用:

    用Pillow打开图片,

    调用image_to_string()方法

     

    注意:自动识别能力有限,属于人工智障级别






























  • 相关阅读:
    Qt快速入门学习笔记(基础篇)
    IDEA 创建文件夹总默认根节点问题解决
    SpringBoot 集成MyBatis 中的@MapperScan注解
    Springboot项目下mybatis报错:Invalid bound statement (not found)
    IDEA maven项目查自动查看依赖关系,解决包冲突问题
    Mybatis-generator/通用Mapper/Mybatis-Plus对比
    Mybatis
    在一个已经使用mybatis的项目里引入mybatis-plus,结果不能共存
    springboot整合图像数据库Neo4j
    Spring Boot:Boot2.0版本整合Neo4j
  • 原文地址:https://www.cnblogs.com/pywjh/p/9778993.html
Copyright © 2011-2022 走看看