Python識別簡單驗證碼
12.1 更新
來自我的博客: PIL 識別簡單驗證碼
已經有完整的代碼了
=======================================
新手, 多多指教
大概思路: 1. 轉換圖片為黑白, 2. 去除干擾, 3. 切割, 4. 識別
<1>
採集足夠的驗證碼圖片
要識別的驗證碼都是簡單的, 字體一致, 無變形, 干擾少,位置固定(適合新手)
採集代碼(隱去網址)
for i in range(500): url = rhttp://xxxx/default3.html urllib.urlretrieve(url, str(i) + .gif)
<2>
切割轉換圖片, 返回為圖片塊
rct 為五個數字的四條邊的位置, 由於位置固定所以通過手動微調得到大概值
import osfrom PIL import Imagedef get_cut(file_name): img = Image.open(file_name) cut_img = [] # 每個數字的範圍 rct = ( (5, 5, 15, 19), # 左邊距 上邊距 右邊距 下邊距 (14, 5, 24, 19), (23, 5, 33, 19), (32, 5, 42, 19), (41, 5, 51, 19) ) # 轉換圖片 bin_img = get_bin(img) # 將圖片分割為五部分 for part in range(5): cut_img.append(bin_img.crop(rct[part])) return cut_img
切割後的圖片大概如下:
保存切割的圖片代碼如下, 測試的時候用:
for i in range(20): img = get_cut(img\ + str(i) + .gif) d = 0 for im in img: d += 1 im.save(cut\ + str(i) + str(d) + .gif)
<3>
把圖片轉換為灰度圖 , 去除噪音部分, 轉換為黑白
由圖可看出, 數字部分顏色比較暗, 背景部分偏亮, 轉換為灰度圖, 將亮的部分去除得到的就是有效的數字部分像素, 閾值可用ps, 或者用代碼計算出亮度信息集中部分, 將高於閾值的部分去除
# 去除圖片噪點並轉為黑白def get_bin(img): bin_img = Image.new(L, img.size, 255) # 新圖片 模式 L灰度 大小 色彩深度 cvt_img = img.convert("L") # 轉換模式為灰度圖 for x in range(img.size[1]): for y in range(img.size[0]): pix = cvt_img.getpixel((y, x)) if pix < 110: # 去噪閾值過濾灰度大於 110 的像素點 bin_img.putpixel((y, x), 0) # 填充新圖片 else: bin_img.putpixel((y, x), 255) return bin_img
<4>
將圖片每個像素點轉換為 0, 1 值對應的字典,1代表有, 0 代表無
# 轉換為矢量def buildvector(img): d1 = {} count = 0 for i in img.getdata(): d1[count] = 0 if i ==255: d1[count] = 1 count += 1 return d1
<5>
識別圖片塊數字, 將要識別的圖片轉換為二值對應的字典, 讀取已知的圖片並與要識別的圖片比較, 比較的方法是對比x每一行, y每一列, 將一樣的值計數統計除以總像素計算出相似度, 並返回相似度最高的圖片的值
# 識別每個圖片塊的內容def get_result(src_img): guess = -1 # 將圖片轉換為二值列表 srcimgbin = buildvector(src_img) # 用於儲存每個對比數字的相似率 simalist = [] for i in range(10): simalist.append(0) # 與每個數字對比 for cp_numb in range(10): cp_count = len(os.listdir(convert_Img\%s % cp_numb)) # 遍歷比較已知數字圖片塊集合目錄 for comp in os.listdir(convert_Img\%s % cp_numb): cpimgpath = convert_Img\ + str(cp_numb) + \ + comp # 將已知塊轉換 cp_bin =buildvector(get_bin(Image.open(cpimgpath))) xy = 0 yx = 0 # 縱向掃描對比 並統計相同 for x in range(10): for y in range(14): if cp_bin[x * y + y] == srcimgbin[x * y + y] == 1: xy += 1 # 橫向掃描對比 for y in range(14): for x in range(10): if cp_bin[y * x + x] == srcimgbin[y * x + x] == 1: yx += 1 # 得出單張圖片相似率 sima = (xy + yx) / 280 # 統計該數相似率 simalist[cp_numb] += sima # 求於個數平均值 simalist[cp_numb] /= cp_count # 得到相似度最高的數字 guess = getmax(simalist) return guess# 獲取列表最大數def getmax(list): li = list max = 0 index = 0 for i in range(len(li)): if max < li[i]: max = li[i] index = i return index
<6>
主函數循環識別一百張張圖片驗證碼內容,將識別結果命名為圖片名
if __name__ == __main__: for i in range(100): # 得到只有黑白值的圖片分割塊 cut_img = get_cut(img\ + str(i) + .gif) result = # 識別每個圖片塊的內容 for im in cut_img: # 將識別的結果連接 result = result + str(get_result(im)) print result # 重命名文件名為識別結果 os.rename(img\ + str(i) + .gif,img\ + result + .gif)
識別結果
待解決問題, 將已標記的圖片先轉換為二值標記文件, 8 會識別為 3 ,原因是還有干擾的點
待更新 . . .
推薦閱讀: