精华内容
下载资源
问答
  • 验证码预处理
    2020-07-05 10:01:13

    前言

    今天看到了一个好东西,和大家分享一下,顺便翻译翻译。
    github源码:https://github.com/Vykstorm/CaptchaDL
    kaggle地址:https://www.kaggle.com/vykstorm/extracting-words-from-images-with-opencv-part-2

    具体就是对验证码做预处理,让我觉得是好东西的是验证码的切割部分。验证码样本:
    在这里插入图片描述
    这种验证码使用一些简单的技巧是无法切割的,而这个大佬用OpenCV做到了,并且切割效果比较理想。

    kaggle可以下载到jupyter的笔记和代码,只需要在本地创建个python的虚拟环境(推荐conda),装上github的requeriments.txt里的包就可以本地测试效果了。(当我们接触一个新东西的时候,先不要去着急的理解原理,我们可以先使用别人的成果来满足自己的好奇心。比如将他的代码全部运行一遍得到了最终的效果,这在后面一步一步的分析的时候才会更有干劲,因为你知道终点你也可以做到,那么过程累一点也无所谓。)

    jupyter内容翻译

    导入相关库

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    import os
    import cv2 as cv
    import pickle
    import warnings
    from itertools import product, repeat, permutations, combinations_with_replacement, chain
    from math import floor, ceil
    
    warnings.filterwarnings('ignore')
    
    %matplotlib inline
    

    加载数据集

    如果kaggle下载慢的可以下载这个:https://download.csdn.net/download/Qwertyuiop2016/12575444(免积分)
    因为jupyter上加载的是kaggle网站上的,我想本地测试就将验证码下载下来本地加载

    import numpy as np
    import os
    import random
    from PIL import Image
    
    img_dir = 'I:/samples/samples' # 验证码路径
    os.chdir(img_dir)
    width, height, img_num = 200, 50, 1000
    # 本来这样选的目的是为了能指定数量和打乱顺序,不过在这里没什么用,因为不训练模型
    imgs = random.sample(os.listdir(), img_num) 
    X = np.zeros((len(imgs), height, width, 1), dtype = np.uint8)  # 这种维度只是为了适应TensorFlow的图片输入格式
    for index, img_name in enumerate(imgs):
        img = Image.open(img_name)
        img_gray = img.convert('L')  # 转换为灰度图
        pix = np.array(img_gray)
        pix = pix.reshape((height, width, 1))  # 将维度为(height, width)转为(height, width, 1)
        X[index] = pix
    

    显示灰度图

    img = X[1][:,:,0]
    plt.imshow(img, cmap='gray')
    

    验证码灰度图

    反转黑白色

    inverted = 255 - img
    plt.imshow(inverted, cmap='gray');
    

    反转黑白

    二值化图片

    ret, thresholded = cv.threshold(inverted, 140, 255, cv.THRESH_BINARY)
    plt.imshow(thresholded, cmap='gray');
    
    1. inverted是图片灰度化的数组
    2. 其中140是二值化的阈值,可以由迭代法和otsu算法得到,具体参考我以前的博客:验证码之二值化
    3. 255为图片像素的最大值
    4. cv.THRESH_BINARY表示大于阈值设为255(就是第三个参数的值),小于阈值设为0,这也就是通常所说的二值化

    在这里插入图片描述
    阈值可以自己用实现算法计算出来,其实OpenCV也内置了otsu算法。实现如下:

    ret2,th2 = cv.threshold(inverted,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
    plt.imshow(th2, cmap='gray')
    

    在这里插入图片描述

    利用中值滤波简单去噪点和干扰线

    blurred = cv.medianBlur(thresholded, 3)
    plt.imshow(blurred, cmap='gray')
    

    第二个参数表示滤波模板的尺寸,值必须为大于1的奇数。在验证码处理中一般为3或者5,太大容易消除验证码特征。
    值为3时:
    在这里插入图片描述
    值为5时:
    在这里插入图片描述
    我看kaggle上那位大佬选的值为3,但我看值为5时效果更佳。不过在下一步操作后,其实两个得到的结果差不了太多,感觉这一步只是顺带的,并不重要。

    形态学操作消除噪点和干扰线

    形态学操作:腐蚀、膨胀、开运算、闭运算等

    首先进行开运算:

    kernel = np.array([
        [0, 0, 1, 0, 0],
        [0, 0, 1, 0, 0],
        [0, 0, 1, 0, 0],
        [0, 0, 1, 0, 0],
        [0, 0, 1, 0, 0],
    ]).astype(np.uint8)
    
    ex = cv.morphologyEx(blurred, cv.MORPH_OPEN, kernel)
    plt.imshow(ex, cmap='gray');
    

    cv.MORPH_OPEN表示开运算(先腐蚀后膨胀),kernel的选择我搜不到相关资料。不过我换全0的效果也差不多,甚至改成全1的也是一样,我又继续试了3x3的全0和全1或者中间为1,同样看不出太大的区别。希望有懂的大佬能说一下。
    效果图:
    在这里插入图片描述
    接着在上面操作完的图片在进行膨胀:

    kernel2 = np.array([
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0],
    [1, 1, 1, 1, 1],
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0]
    
    ]).astype(np.uint8)
    
    ex2 = cv.morphologyEx(ex, cv.MORPH_DILATE, kernel2)
    plt.imshow(ex2, cmap='gray');
    

    在这里插入图片描述

    对blurred的那张图和膨胀后的图像进行与运算

    与运算:即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“与”操作,1&1=1,1&0=0,0&1=0,0&0=0

    mask = ex2
    processed = cv.bitwise_and(mask, blurred)
    plt.imshow(processed, cmap='gray')
    

    在这里插入图片描述

    寻找轮廓线

    contours, hierachy = cv.findContours(processed, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE)
    contours = [contours[k] for k in range(0, len(contours)) if hierachy[0, k, 3] == -1]
    contours.sort(key=lambda cnt: cv.boundingRect(cnt)[0])
    plt.imshow(cv.drawContours(cv.cvtColor(img, cv.COLOR_GRAY2RGB), contours, -1, (255, 0, 0), 1, cv.LINE_4));
    

    在这里插入图片描述

    针对找出的轮廓线画出矩形框

    contour_bboxes = [cv.boundingRect(contour) for contour in contours]
    img_bboxes = cv.cvtColor(img, cv.COLOR_GRAY2RGB)
    for bbox in contour_bboxes:
    	left, top, width, height = bbox
    	img_bboxes = cv.rectangle(img_bboxes,
    							(left, top), (left+width, top+height),
    							, 255, 0), 1)
    plt.imshow(img_bboxes, cmap='gray');
    

    在这里插入图片描述
    画了两个框的原因是上一步找出了两条轮廓线,从返回的contours这个列表有几个元素可以看出,即有len(contours)个框.

    训练一个分类器来识别每个框框有多少个字符

    特征有:框宽度、框高度、框面积、框面积/(框高度*框宽度)、框周长

    我们训练一个根据上面五个特征来得到框框有几个字符的分类器,大佬使用的是SVC分类器。不过我并没有找到分类器代码的实现,只有一个已经训练好的分类器。
    提取特征:

    contours_features = pd.DataFrame.from_dict({
    	'bbox_width': [bbox[2] for bbox in contour_bboxes],
    	'bbox_height': [bbox[3] for bbox in contour_bboxes],
    	'area': [cv.contourArea(cnt) for cnt in contours],
    	'extent': [cv.contourArea(cnt) / (bbox[2] * bbox[3]) for cnt, bbox in zip(contours, contour_bboxes)],
    	'perimeter': [cv.arcLength(cnt, True) for cnt in contours]
    })
    

    数据格式
    加载已经训练好的分类器:https://github.com/Vykstorm/CaptchaDL/blob/master/models/.contour-classifier

    with open('I:/contour-classifier', 'rb') as file:
        contour_classifier = pickle.load(file)
    

    对数据进行标准化操作(削弱值特别大的特征对结果的影响):
    https://github.com/Vykstorm/CaptchaDL/blob/master/models/.contour-classifier-preprocessor

    with open('I:/contour-classifier-preprocessor', 'rb') as file:
    	contour_features_scaler = pickle.load(file)
    contour_features = contour_features_scaler.transform(contours_features[['bbox_width', 'bbox_height', 'area', 'extent', 'perimeter']])
    # 得到的contour_features:
    #array([[ 2.1661931 ,  1.40786863,  2.87483795,  0.11734141,  1.81692393],
    #       [-0.62741894, -0.37829382, -0.6341117 ,  0.72145767, -0.6275891 ]])
    
    

    预测结果:

    contour_num_chars = contour_classifier.predict(contour_features)`
    # array([4, 1], dtype=uint8)
    

    符合我们人眼看到的第一个框四个字符,第二个框一个字符。

    后面的一些操作就不解释了,就是将包含多个字符的框等比例切割,然后再将切割后每个字符扩充到同样的大小。

    更多相关内容
  • 学习验证码的破解/识别技术,不仅可以知道验证码的原理,而且可以让你知道怎样才能防止验证码被破解。 最常见的验证码主要有以下几种: 1、四位数字,随机的一数字字符串,最原始的验证码,验证作用几乎为零。 2、...
  • 完美验证码识别系统

    2018-01-07 03:49:10
    知道还有没有其他问题) 3.编辑字库页面增加个选中框[添加字库后自动下载图片],使用批量下载图片,可以快速添加字库 4.使用截图工具,截取图片后,会自动切换到划线工具. [2017-05-17] 完美验证码识别系统V2.3 1....
  • 很多小伙伴们反馈,在web自动化的过程中,经常会被登录的验证码给卡住,不知道如何去通过验证码的验证。今天专门给大家来聊聊验证码的问题,一般的情况下遇到验证码我们可以都可以找开发去帮忙解决,关闭验证码,...
  • 很多人对CAPTCHA(验证码)很熟悉,但是很少有人知道其含义:全自动区分计算机和人类的图灵测试。通俗的讲就是是一种区分人和人工智能程序的方法。很多的网页都设置了验证码,常见的就是由“字母数字”组成的图片,...
  • 前言 写爬虫有一个绕不过去的问题...由于是实验性质的,文中用到的验证码均为程序生成而不是批量下载真实的网站验证码,这样做的好处就是可以有大量的知道明确结果的数据集。 当需要真实环境下需要获取数据时,可以
  • 写爬虫有一个绕不过去的...由于是实验性质的,文中用到的验证码均为程序生成而不是批量下载真实的网站验证码,这样做的好处就是可以有大量的知道明确结果的数据集。 当需要真实环境下需要获取数据时,可以使用结合各个
  • 主要介绍了js实现点击获取验证码倒计时效果,这种效果大家经常遇到,想知道如何实现的,请阅读本文。
  • 一般来说,我们会把验证码的值用Session存储起来,通过对比用户提交的验证码和Session中的验证码,就可以知道输入是否正确。由于Session会占用服务器资源,我曾经想过是否可以把验证码的值加密后存储在Cookie中。...
  • 大家知道简单数字或者字母验证码很容易被破解,但是算式验证码或者中文汉字验证码不容易被破解,所以建议大家在使用验证码的时候,尽量用算式验证码或者中文汉字验证码。 下面是我写的两种验证码代码,有用到的朋友...
  • PHP随机验证码含有5种样式,包含中文验证码,英文验证码,数字验证码共5种样式
  • 主要介绍了Android实现点击获取验证码倒计时效果,这种效果大家经常遇到,想知道如何实现的,请阅读本
  • 大家知道简单数字或者字母验证码很容易被破解,但是算式验证码或者中文汉字验证码不容易被破解, 所以建议大家在使用验证码的时候,尽量用算式验证码或者中文汉字验证码。 下面是我写的两种验证码代码,有用到的朋友...
  • 使用Tesseract-OCR在loadrunner中识别验证码知道还有一个Tesseract-OCR可以用来识别图片上的文字(验证码)。 有一个Tesseract-OCR可以用来识别图片上的文字(验证码)。  在code.google上下载了tesseract-ocr-setup-...
  • 本文列举两个例子:某象和某验的滑动验证 一、某验:aHR0cHM6Ly93d3cuZ2VldGVzdC5jb20vZGVtby9...那你应该会想到,那段js中会生成canvas,然后使用它下面的一些方法,实现图片的还原操作,所以我们需要知道他啥时
  • 在很多时候都需要用到验证码,前端验证码需要知道Html5中的canvas知识点。验证码生成步骤是:1.生成一张画布canvas 2.生成随机数验证码 3.在画布中生成干扰线 4.把验证码文本填充到画布中 5.点击画布更换验证码
  • 在下次请求同一网站时,会发送该Cookie给服务器,这样服务器就知道该用户是否合法以及是否需要重新登录。 Python提供了基本的cookielib库,在首次访问某页面时,cookie便会自动保存下来,之后访问其
  • 后来知道是在调用验证码的地方 写上 Public function verify(){ import('ORG.Util.Image'); Image::buildImageVerify(); } 改成这样就行了: Public function verify(){ import('ORG.Util.Image'); ob_clean()
  • 在以前的我们已经知道这种简单的粘连可以通过控制阈值来实现分割,这里我们使用滴水算法。 首先使用之前文章中介绍的垂直投影或者连通域先进行一次切割处理,得到结果如下: 针对于最后粘连情况来使用滴水算法处
  • 今天这篇文章主要记录一下如何切分验证码,用到的主要库就是Pillow和Linux下的图像处理工具GIMP。首先假设一个固定位置和宽度、无粘连、无干扰的例子学习一下如何使用Pillow来切割图片。 使用GIMP打开图片后,按 ...
  • 我们知道验证码为了制作干扰,会把图片弄成五颜六色的样子,而我们首先就是要去除这些干扰,这一步就需要不断试验了,增强图片色彩,加大对比度等等都可以产生帮助。 在经过各种对图片的操作之后,终于找到了比较...
  • 验证码无处不在,有人问我,你知道达芬奇密码下面是什么吗,对,答案就是达芬奇验证码验证码一个最主要的作用就是防止恶意暴力破解登录,防止不间断的登录尝试,有人说其实可以在服务器端对该终端进行登录间隔...
  • php实实现现汉汉字字验验证证...本文实例讲述了php实现汉字验证码和算式验证码的方法分享给大家供大家参考具体分析如下 大家知道简单数字或者字母验证码很容易被破解但是算式验证码或者中文汉字验证码不容易被破解 所以
  • 最近正在学习php入门,现在刚入门,所以许多都不知道,就从最基础的学起,不会的上网查,然后把它记在这个法宝内
  • 但是,也知道自己的局限,所以特意写出来,希望各路大神指点一下,能够更多的拓展自己的视野。 php代码如下:实现验证码的功能 <?php /** * @param int $width 宽度,默认为120 * @param int $height 高度,默认...
  • 针对复杂背景验证码过滤背景源码 经过优化后。我电脑处理速度是150-200毫秒(以一键处理为准) 增加了一些其它功能,都是根据颜色数量来操作的。 1.首先点击初始化 等初始化成功(这里主要是加入列表框耗时间,实际...
  • Lapti工作量验证码 通过本地托管的工作量证明算法来保护繁重的API方法。 主意 如果API中有一些方法需要花费很多时间来服务,则您可能需要防止它们受到DDoS攻击。 下文描述了一种这样做的方法。 服务器保留一些秘密...
  • 图片验证码工具类

    2017-03-21 19:59:45
    图片验证码生成工具类
  • php 验证码实例代码

    2020-10-29 02:14:11
    首先验证码的原理就是,画一张图片,然后在这张图片上写一些字,然后加一些干扰的线条,像素点之类的东西就ok了,这里要使用php那就要知道php中画图的函数是那些,然后拿来用便是了。
  • python验证码识别

    2020-12-30 10:29:52
    写爬虫有一个绕不过去的问题就是验证码,现在验证码分类大概有4种:图像类滑动类点击类语音类今天先来看看图像类,这类验证码大多是数字、字母的组合,国内也有使用汉字的。在这个基础上增加噪点、干扰线、变形、...

    写爬虫有一个绕不过去的问题就是验证码,现在验证码分类大概有4种:图像类

    滑动类

    点击类

    语音类

    今天先来看看图像类,这类验证码大多是数字、字母的组合,国内也有使用汉字的。在这个基础上增加噪点、干扰线、变形、重叠、不同字体颜色等方法来增加识别难度。

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

    增加对比度(可选)

    二值化

    降噪

    倾斜校正分割字符

    建立训练库

    识别

    由于是实验性质的,文中用到的验证码均为程序生成而不是批量下载真实的网站验证码,这样做的好处就是可以有大量的知道明确结果的数据集。

    当需要真实环境下需要获取数据时,可以使用结合各个大码平台来建立数据集进行训练。

    生成验证码这里我使用 Claptcha 这个库,当然 Captcha 这个库也是个不错的选择。

    为了生成最简单的纯数字、无干扰的验证码,首先需要将claptcha.py的285行_drawLine做一些修改,我直接让这个函数返回None,然后开始生成验证码:

    这里需要注意ubuntu的字体路径,也可以在网上下载其他字体使用。生成验证码如下:

    可以看出,验证码有形变。对于这类最简单的验证码,可以直接使用谷歌开源的tesserocr来识别。

    首先安装:

    然后开始识别:

    可以看出,对于这种简单的验证码,基本什么都不做识别率就已经很高了。有兴趣的小伙伴可以用更多的数据来测试,这里我就不展开了。

    接下来,在验证码背景添加噪点来看看:

    生成验证码如下:

    识别:

    效果还可以。接下来生成一个字母数字组合的:

    生成验证码如下:

    第3个为小写字母o,第4个为大写字母O,第5个为数字0,第6个为小写字母z,第7个为大写字母Z,最后一个是数字2。人眼已经跪了有木有!但现在一般验证码对大小写是不做严格区分的,看自动识别什么样吧:

    人眼都跪的计算机当然也废了。但是,对于一些干扰小、形变不严重的,使用tesserocr还是十分简单方便的。然后将修改的claptcha.py的285行_drawLine还原,看添加干扰线的情况。

    加了条干扰线就完全识别不出来了,那么有没有什么办法去除干扰线呢?

    虽然图片看上去是黑白的,但还需要进行灰度处理,否则使用 load() 函数得到的是某个像素点的RGB元组而不是单一值了。处理如下:

    处理后的图片如下:

    可以看出处理后图片锐化了很多,接下来尝试去除干扰线,常见的4邻域、8邻域算法。所谓的X邻域算法,可以参考手机九宫格输入法,按键5为要判断的像素点,4邻域就是判断上下左右,8邻域就是判断周围8个像素点。如果这4或8个点中255的个数大于某个阈值则判断这个点为噪音,阈值可以根据实际情况修改。

    处理后的图片如下:

    好像……根本没卵用啊?!确实是这样的,因为示例中的图片干扰线的宽度和数字是一样的。对于干扰线和数据像素不同的,比如Captcha生成的验证码:

    从左到右依次是原图、二值化、去除干扰线的情况,总体降噪的效果还是比较明显的。另外降噪可以多次执行,比如我对上面的降噪后结果再进行依次降噪,可以得到下面的效果:

    再进行识别得到了结果:

    另外,从图片来看,实际数据颜色明显和噪点干扰线不同,根据这一点可以直接把噪点全部去除,这里就不展开说了。

    感谢 大家转发 关注

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 45,868
精华内容 18,347
关键字:

怎样知道验证码