python+sklearn自动识别验证码实例

tech2023-05-28  55

文章目录

前言一、灰度化二、二值化及去噪点三、图片切割四、手动标注五、开始训练六、使用训练好的模型进行识别

前言

在爬虫的工作中,经常会遇到各种各样的验证码。所以打算在这儿记录一下几种不同的识别方法,做一下笔记。

图片验证码的几种识别方式

从某网站获取到的验证码 处理流程总共分为以下几步: 1.读取图片,并调整图片尺寸 2.对图片进行灰度处理 3.根据自己设置的阈值,对图片进行二值化处理 4.降噪处理,去除干扰的像素点及像素块 5.对图片进行切割,获得单个字符,并进行人工标注 6.使用sklearn的svm分类器进行训练,得到模型 7.使用训练得到的模型进行验证码识别

下面分别为每个步骤的核心代码及示例

一、灰度化

img = cv2.imread("image14.png") # 转换为灰度图 im_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

二、二值化及去噪点

# 二值化处理 ret, im_inv = cv2.threshold(im_gray, 150, 255, 0) show_gray_img(im_inv) # 去除孤立点,噪点 img_clear = noise_remove_cv2(im_inv, 1)

去燥点的方法

# 去除噪点 def noise_remove_cv2(image, k): def calculate_noise_count(img_obj, w, h): """ 计算邻域非白色的个数 """ count = 0 width, height = img_obj.shape for _w_ in [w - 1, w, w + 1]: for _h_ in [h - 1, h, h + 1]: if _w_ > width - 1: continue if _h_ > height - 1: continue if _w_ == w and _h_ == h: continue if img_obj[_w_, _h_] < 230: # 二值化的图片设置为255 count += 1 return count w, h = image.shape for _w in range(w): for _h in range(h): if _w == 0 or _h == 0: image[_w, _h] = 255 continue # 计算邻域pixel值小于255的个数 pixel = image[_w, _h] if pixel == 255: continue if calculate_noise_count(image, _w, _h) < k: image[_w, _h] = 255 return image

去除噪点后的验证码

三、图片切割

# 垂直分割投影法分割图片 img_list = cut_vertical(img_clear) t = 1 for i in img_list: resize_img = cv2.resize(i, (15, 30)) # 重新定义大小 # 这里可以对切割到的图片进行操作,显示出来或者保存下来 cv2.imwrite(os.path.join(new_image_path, file + "_" + str(t) + '.jpg'), resize_img) t += 1 def cut_vertical(img_list, cvalue=255): """ 投影法竖直切割图片的数组 :param img_list: 传入的数据为一个由(二维)图片构成的数组,不是单纯的图片 :param cvalue: 切割的值 同cut_level中的cvalue :return: 切割之后的图片的数组 """ # 如果传入的是一个普通的二值化的图片,则需要首先将这个二值化的图片升维为图片的数组 if len(np.array(img_list).shape) == 2: img_list = img_list[None] r_list = [] for img_i in img_list: end = 0 for i in range(len(img_i.T)): if count_number(img_i.T[i], cvalue) >= img_i.shape[0]: star = end end = i if end - star > 1: r_list.append(img_i[:, star:end]) return r_list

切割后的图片

四、手动标注

将切割后相同的字符放入同一文件夹下,文件夹名字作为标注名,如图。

五、开始训练

这里使用sklearn.svm这个支持向量机的算法,来对数据进行分类。(关于svm的讲解,可以看看知乎大神的理解https://www.zhihu.com/question/21094489 ),通过fit进行训练后,将训练的结果保存到pkl文件里,其实里面都是0和1的特征值。

letterSVM = SVC(kernel="linear", C=1).fit(train_set_x, train_set_y) # 生成训练结果 joblib.dump(letterSVM, 'data/letter.pkl')

六、使用训练好的模型进行识别

def ocrImg(fileName): captcha = [] clf = joblib.load('data/letter.pkl') img = cv2.imread(fileName) # 转换为灰度图 im_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化处理 ret, im_inv = cv2.threshold(im_gray, 140, 255, 0) # 去除孤立点,噪点 img_clear = noise_remove_cv2(im_inv, 1) # 垂直分割投影法分割图片 img_list = cut_vertical(img_clear) for i in img_list: res1 = cv2.resize(i, (28, 28)) data = res1.reshape(784) data = data.reshape(1, -1) oneLetter = clf.predict(data)[0] # print(oneLetter) captcha.append(oneLetter) captcha = [str(i) for i in captcha] print("the captcha is :%s" % ("".join(captcha))) ocrImg("test_img/test_img_1.png")

源码及训练的图片等已上传github(https://github.com/deepcoldwing/verification_code)

最新回复(0)