1. 程式人生 > >python實現驗證碼的非連線字元的分割演算法

python實現驗證碼的非連線字元的分割演算法

最近在抓取某網站時候,遇到了驗證碼的問題,想要破解一下驗證碼,示例驗證碼如下

這種驗證碼位置不固定,並且有傾斜,垂直投影會有交叉的部分,所以不適合用垂直切割的辦法,受影象處理中洪水演算法的啟發,想到一種思路

洪水演算法 參見 http://blog.csdn.net/Trent1985/article/details/44904431

常見實現辦法有遞迴,掃描線演算法等,本文針對的驗證碼不適合用掃描線演算法,遂用遞迴實現

以下是核心程式碼:

import numpy as np
import cv2
from PIL import Image
def getPoint(x,y,data,subdata=None):
    a=[0,-1,0,1,0,-2,0,2,0,-3,0,3,0,-4,0,4,0,-5,0,5]
    b=[1,0,-1,0,2,0,-2,0,3,0,-3,0,4,0,-4,0,5,0,-5,0]
    width,height=data.shape
    if subdata is None:
        subdata=[]
    if x>5 and y<height-5 and y>5 and x<width-5:
        for i in range(20):
            if data[x+a[i]][y+b[i]]==1:
                subdata.append((x+a[i],y+b[i]))
                data[x+a[i]][y+b[i]]=2
                getPoint(x+a[i],y+b[i],data,subdata)
    subdata.append((x,y))

def getcell(data):
    list1=[]
    index=0
    flag=True
    for y in range(data.shape[1]):
        for x in range(data.shape[0]):
            if data[x][y]==1:
                if list1:
                    for i in range(len(list1)):
                        if (x,y) in list1[i]:
                            flag=False
                if not flag:
                    continue
                list1.append([])
                getPoint(x,y,data,list1[index])#呼叫流水演算法
                index+=1
            else :
                continue
    
    for index in range(len(list1)):
        l=list1[index][0][0]
        t=list1[index][0][1]
        r=list1[index][0][0]
        b=list1[index][0][1]
        for i in list1[index]:
            x=i[0]
            y=i[1]
            l=min(l,x)
            t=min(t,y)
            r=max(r,x)
            b=max(b,y)
        w=r-l+1
        h=b-t+1
        if (w*h <8):#去除小色塊
            continue
        img0=np.zeros([w,h])#建立全0矩陣
        for x,y in list1[index]:
            img0[x-l][y-t]=1
        img0[img0<1]=255
        img1=Image.fromarray(img0)
        img1=img1.convert('RGB')
        img1.save('img2/'+str(index)+'.png')
if __name__=="__main__":
    filename='captcha1.png'
    data=cv2.imread(filename,2) 
    allimg=getcell(data)

以上是我個人實現的解決方案,雖然算不上最優,但基本能夠滿足需求

效果圖

9:         5:              4:         n:

有不足之處歡迎指出,也歡迎提出更優的解決方案