python實現驗證碼的非連線字元的分割演算法
阿新 • • 發佈:2019-01-04
最近在抓取某網站時候,遇到了驗證碼的問題,想要破解一下驗證碼,示例驗證碼如下
這種驗證碼位置不固定,並且有傾斜,垂直投影會有交叉的部分,所以不適合用垂直切割的辦法,受影象處理中洪水演算法的啟發,想到一種思路
洪水演算法 參見 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:
有不足之處歡迎指出,也歡迎提出更優的解決方案