利用hog特徵訓練svm識別位置固定驗證碼
阿新 • • 發佈:2018-12-16
RT(純做記錄)
說要了解github但是還沒邁出艱難的第一步,主要是程式碼太水。今天整理了一下,並且用了sklearn模組的svm進行hog特徵提取來識別驗證碼,一個原因是上一篇部落格的svm訓練出來的模型,對於z的識別一直錯誤,一直識別成S。所以對特徵這塊來試試hog特徵,對於我的樣本集,效果非常好。
訓練集
首先制定訓練集,上一篇部落格 中有說到,如何手工製作驗證碼訓練集,但是沒有圖,這裡詳細帶圖做下記錄。
第一步爬圖片
import itertools
import time
from os import walk
from os.path import splitext
import requests
header = {
'Host': 'xxxxxxxxxxxxxx',
'Referer': 'xxxxxxxxxxxxx',
'Connection': 'xxxxxxxxxx'
}
def max_file_name():
filenames_list = [int(splitext(i)[0]) for dirpath, dirnames, filenames in walk('CAPTCHA') for i in filenames]
return max(filenames_list + [0, ])
def get_img (filename):
response = requests.get(f'xxxxxxxxx', headers=header)
response.raise_for_status()
with open(f'CAPTCHA/{filename}.gif', 'wb') as f:
f.write(response.content)
if __name__ == '__main__':
filename = max_file_name()+1
for i in itertools.count(filename):
get_img( i)
print(i-filename+1)
time.sleep(5)
別問,問就上網查。還是不會就手動儲存。手動儲存的話,需要儲存的圖片必須包含所有字母數字。也就是0-9,A-Z都出現過。 假設完美情況就是9張圖就可以了。不完美就慢慢扣。
第二步轉換png
因為cv2不支援讀取gif,我就轉換了。
# 檔名:gif2png.py
from PIL import Image
from numpy import *
def iter_frames(im):
try:
i= 0
while 1:
im.seek(i)
imframe = im.copy()
if i == 0:
palette = imframe.getpalette()
else:
imframe.putpalette(palette)
yield imframe
i += 1
except EOFError:
pass
def open_dir(dirpath, savepath):
i = 0
for root, dirs, filenames in os.walk(dirpath):
for file in filenames:
i += 1
img = Image.open(dirpath+"/"+ file)
for b, frame in enumerate(iter_frames(img)):
frame.save(savepath + f'{i}.png')
if __name__ == '__main__':
path = r"D:\project\tenssact\data\gif_path"
save_path = r"D:\project\tenssact\data\ong_path/"
open_dir(path,save_path)
第三步二值化一下
檔名png2thre
import cv2 as cv
import os
import numpy as np
def custom_threshold(path):
# path = r"D:\project\tenssact\svm\png_path" + "/" + image
image = cv.imread(path)
gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY) #把輸入影象灰度化
h, w =gray.shape[:2]
m = np.reshape(gray, [1,w*h])
mean = m.sum()/(w*h)
print("mean:",mean)
ret, binary = cv.threshold(gray, 240, 255, cv.THRESH_BINARY)
# cv.namedWindow("binary2", cv.WINDOW_NORMAL)
# cv.imshow("binary2", binary)
return binary
def png2thre(dirpath,savepath):
i = 0
for root,dirs,filenames in os.walk(dirpath):
for file in filenames:
path = dirpath + "/" + file
# i += 1
img = custom_threshold(path)
cv.imwrite(savepath+ f'{i}.png',img)
if __name__ == '__main__':
path = r"D:\project\tenssact\data\png_path/"
save_path = r"D:\project\tenssact\data\thre_path/"
open_dir(path,save_path)
第四步分割一下
from PIL import Image
from numpy import *
def cutImg(img): #影象切割
s = 5
w = 11
h = 16
t = 3
cut_img = []
for i in range(4):
pic = img.crop((s + w * i+i, t, s + w * (i + 1)+i, h))
cut_img.append(pic)
return cut_img
def split_img(dirpath, savepath):
i = 0
for root, dirs, filenames in os.walk(dirpath):
for file in filenames:
img = Image.open(dirpath+"/"+file)
imgs = cutImg(img)
for im in imgs:
im.save(savepath+f'{i}.png')
i += 1
path = r"D:\project\tenssact\data\thre_path"
savepath = r"D:\project\tenssact\data\test/"
split_img(path,savepath)
分割之後會出現一堆被分割的圖片,這時建立36個資料夾,然後命名為0-36,按照0-9,A-Z的順序,一張張圖塞到對應的資料夾裡。塞完了,訓練集建立成功了!!。
訓練
import cv2
from skimage import feature as ft
from sklearn import svm
import os
from sklearn.externals import joblib
feat = []
labels = []
for file in os.listdir(r"D:\project\tenssact\data\test/"):
file_path = os.path.join(r"D:\project\tenssact\data\test/", file)
label = file
for _,dirs,filenames in os.walk(file_path):
for file in filenames:
img = cv2.imread(_+"/"+file)
im = cv2.resize(img,(64,64))
features = ft.hog(im, # input image
block_norm = 'L1', # block norm : str {‘L1’, ‘L1-sqrt’, ‘L2’, ‘L2-Hys’}, optional
transform_sqrt = True, # power law compression (also known as gamma correction)
feature_vector=True, # flatten the final vectors
visualise=False) #
feat.append(features)
labels.append(label)
clf = svm.SVC()
clf.fit(feat,labels)
joblib.dump(clf, "./model")
預測
from gif2png import *
from split_train_img import *
from skimage import feature as ft
from sklearn.externals import joblib
def swich_num(num):
if num <= 9:
out = int(num)
else:
for i in range(27):
if num == 10+i:
num = chr(65+i)
out = num
return (out)
path = r"D:\project\sklearn_svm\gif"
save_path = r"D:\project\sklearn_svm\png/"
save1_path = r"D:\project\sklearn_svm\thre/"
save2_path = r"D:\project\sklearn_svm\split/"
open_dir(path,save_path)
png2thre(save_path,save1_path)
split_img(save1_path,save2_path)
feat = []
for _,dirs,filenames in os.walk(save2_path):
fet = []
for file in filenames:
img = cv2.imread(save2_path+file)
im = cv2.resize(img,(64,64))
features = ft.hog(im, # input image
block_norm='L1', # block norm : str {‘L1’, ‘L1-sqrt’, ‘L2’, ‘L2-Hys’}, optional
transform_sqrt=True, # power law compression (also known as gamma correction)
feature_vector=True, # flatten the final vectors
visualise=False) #
fet.append(features)
feat.append(fet)
clf = joblib.load("./model")
final = []
for fet in feat:
pred = clf.predict(fet)
for num in pred:
pred = swich_num(int(num))
final.append(pred)
print (final)