如何用python搞定验证码中的噪点

    添加时间:2013-7-29 点击量:

    靠山:伴侣在为关山口男人职业技巧黉舍写一款校园应用,于是找我写一个学生选课体系的登录接口.为了搞定这个接口,我不得不先搞定这个体系的验证码.


    验证码可能是这个样子


    看上去不怎么难,没有干扰线没有粘连没有扭曲.但我还是没能用pytesser直接将它辨认出来,因为傍边有噪点和其他靠山噪声的存在.我的工作就是去掉这些憎恶的器材


    先介绍一下,我们的对象:


    1.Pytesser  它是基于一个c说话实现名为tesser的辨认对象的python封装.可惜斗劲笨,只能做最简单的辨认并且不熟悉汉字


    2.Requests  它是我们喜好写爬虫的孩子的最爱,供给人道化的接口,价格是落空了一点效力(写python就别推敲效力啦)


    3.BeautifulSoup  它和Requests是一对好机油,让提取文档中所需的内容变成一件简单的工作


    4.PIL      它是今天的主角,PIL是专门用作图像处理惩罚的库,很好很强大.谙练的人甚至可以用它来P图


    如何写爬虫去实现模仿登录此处不细说,下面说说怎么解决验证码辨认


    解决思路如下:


    1.先用PIL对图像做一次图像加强,因为原图中数字的边沿和靠山中的噪声并不是太分明,做了加强之后能将两者分别.若是不分别,可能会在去噪点的时辰导致数字中有项目组会缺失



    im = Image.open(randomimage/randomImage11.jpg
    im
    = ImageEnhance.Sharpness(im).enhance(3)


    参数为3是经过实验之后感触感染斗劲幻想的值,太强不好,太弱也不好


    2.做完预处理惩罚之后,就是去靠山噪声了.靠山噪声指的是靠山中各类明暗变换的色块,肉眼也许不会重视到这个.然则它的存在会给辨认带来影响.我最初的做法是将图像转换为只有曲直短长两色,如许天然就将噪声转换成了噪点.


    结果如图


    但我能去掉噪点,成为如许




    想到的是种子染色法 ,什么是种子染色法请参看这个链接


    为了防止坏链,此处做项目组转载


    种子染色法英文叫做Flood Fill ,实际上Flood Fill这个名称更贴切一点,因为这个办法感化在一个图的结点上时好似洪水一样“覆没”与之相连的其他结点并以雷同的体式格式伸展出去,这个办法凡是用于策画一个图的极大连通子图(这里的“图”是图论的概念)。假想一个无向图,我们从这个图中一个未标号(“标号”可以懂得为“染色”)的结点开端,将此结点和从这个结点出发可达的所有结点都付与雷同的标号(染上雷同的色彩),那么我们就获得了这些被标号的结点所构成的一个极大连通子图,搜刮下一个未标号的结点并反复上述过程我们便可以找到所有的极大连通子图。“染色”的过程可以用DFS或者BFS实现,若是结点数为V,边数为E,因为我们在Flood Fill过程中“拜访”每个结点两次,“拜访”每条边两次,所以获得所有极大连通子图的时候错杂度为o(V+E) 。


    来自Wikipedia的一个示例:



    想象每个白色方块为图中的结点,相邻的方块(高低阁下)有边相连,那么这个图就有三个极大连通子图,这演示了Flood Fill查找此中一个极大连通子图的过程。


    在这是借要用种子染色法策画每块的面积,然后把小体积的块算作噪点去除.


    代码在这




    def check(j,i):
    
    try:
    if pix[j,i] == 0 and matrix[j][i] != -1:
    return True
    else:
    return False
    except:
    return False

    def juli(r,s):
    return abs(r[0]-s[0])+abs(r[1]-s[1])+abs(r[2]-s[2])

    for i in range(w):
    for j in range(h):
    r
    = [0,0,0]
    s
    = [0,0,0]
    if pix[j,i] == 0:
    if check(j-1,i):
    r[0],r[
    1],r[2] = im2.getpixel((j,i))
    s[0],s[
    1],s[2] = im2.getpixel((j-1,i))
    print r
    print s
    print -55
    if juli(r,s) <=l:
    matrix[j][i]
    = matrix[j-1][i]
    maps[str(matrix[j][i])]
    +=1
    elif check(j-1,i-1):
    r[0],r[
    1],r[2] = im2.getpixel((j,i))
    s[0],s[
    1],s[2] = im2.getpixel((j-1,i-1))
    if juli(r,s) <=l:
    matrix[j][i]
    = matrix[j-1][i-1]
    maps[str(matrix[j][i])]
    +=1
    elif check(j,i-1):
    r[0],r[
    1],r[2] = im2.getpixel((j,i))
    s[0],s[
    1],s[2] = im2.getpixel((j-1,i))
    if juli(r,s) <=l:
    matrix[j][i]
    = matrix[j][i-1]
    maps[str(matrix[j][i])]
    +=1
    elif check(j+1,i+1):
    r[0],r[
    1],r[2] = im2.getpixel((j,i))
    s[0],s[
    1],s[2] = im2.getpixel((j+1,i+1))
    if juli(r,s) <=l:
    matrix[j][i]
    = matrix[j+1][i+1]
    maps[str(matrix[j][i])]
    +=1
    elif check(j,i+1):
    r[0],r[
    1],r[2] = im2.getpixel((j,i))
    s[0],s[
    1],s[2] = im2.getpixel((j,i+1))
    if juli(r,s) <=l:
    matrix[j][i]
    = matrix[j][i+1]
    maps[str(matrix[j][i])]
    +=1
    elif check(j-1,i+1):
    pr[0],r[
    1],r[2] = im2.getpixel((j,i))
    s[0],s[
    1],s[2] = im2.getpixel((j-1,i+1))
    if juli(r,s) <=l:
    matrix[j][i]
    = matrix[j-1][i+1]
    maps[str(matrix[j][i])]
    +=1
    elif check(j+1,i-1):
    r[0],r[
    1],r[2] = im2.getpixel((j,i))
    s[0],s[
    1],s[2] = im2.getpixel((j+1,i-1))
    if juli(r,s) <=l:
    matrix[j][i]
    = matrix[j+1][i-1]
    maps[str(matrix[j][i])]
    +=1
    elif check(j+1,i):
    r[0],r[
    1],r[2] = im2.getpixel((j,i))
    s[0],s[
    1],s[2] = im2.getpixel((j+1,i))
    if juli(r,s) <=l:
    matrix[j][i]
    = matrix[j+1][i]
    maps[str(matrix[j][i])]
    +=1
    else:
    n
    +=1
    maps[str(n)]
    =1
    matrix[j][i]
    = n

    for i in range(w):
    for j in range(h):
    if matrix[j][i]!=-1 and maps[str(matrix[j][i])]<=2:
    im.putpixel((j,i),
    255)


    View Code


    成果呢,不是很幻想因为这个别积参数设小了,噪点没去干净,设大了数字项目组可能也去了一小块.最首要的是这里噪点的大小不是很规律,很难找到一个不错的面积参数.


    失败只是临时的,经过调查发明靠山噪声色彩明显比数字要浅的多.这也意味着它的RGB值要比数字小的多,经由过程解析RGB值能去掉大项目组噪声,剩下来的噪点可以再经由过程种子染色法处理惩罚.也就是说,分别在两张(分别是曲直短长和彩色)上获取信息,在一张上做处理惩罚最后做辨认


    核心代码在这



    r[0],r[1],r[2] = im2.getpixel((j,i))
    
    if r[0]+r[1]+r[2]>=400 or r[0]>=250 or r[1]>=250 or r[2]>=250 :
    im2.putpixel((j,i),(
    255,255,255))


     至此,本次识此外题目就搞定啦,成功率在50%以上根蒂根基满足接口的需求


    想交换或想要源码的伴侣可以邮件接洽

    无论对感情还是对生活,“只要甜不要苦”都是任性而孩子气的,因为我们也不完美,我们也会伤害人。正因为我们都不完美,也因为生活从不是事事如意,所以对这些“瑕疵”的收纳才让我们对生活、对他人的爱变得日益真实而具体。—— 汪冰《世界再亏欠你,也要敢于拥抱幸福》
    分享到: