上一期的分割方法以失败告终(Python盘纪念币系列之二:识别验证码 02)。问题摆在这里总要解决,所以我想了另外一个方法
字符分割
第一种方法宣告失败。重新仔细观察图片,发现所有验证码图片中的字符大概都占据了原始图片1/4
的位置。那是否可以将原始图片均匀切割成四等份,刚好每个字符都在独立的块中呢?下面是算法步骤:
-
图片转换为灰度图
imagecap = get_gif_first_frame('1.jpg') cap = cv2.cvtColor(cap, cv2.COLOR_BGR2GRAY)
-
将图片中像素值小于某个数的像素像素值全部置零,有效降低干扰
image_, thresh = cv2.threshold(cap, 150, 255, cv2.THRESH_BINARY)
-
图片切为四份
imagewidth = thresh.shape[1] chars = [thresh[:, 0:int(width / 4)], thresh[:, int(width / 4):int(width / 2)], thresh[:, int(width / 2):int(3 * width / 4)], thresh[:, int(3 * width / 4):]]
-
在水平和垂直方向上去掉字符块上下左右侧的黑边,以第一个字符块在垂直方向的处理方法为例,以下是的具体算法步骤:
-
将每一行的像素值相加
vertical = [sum(char_patch[index, :]) for index in range(char_patch.shape[0])]
-
取出非零元素的下标,按照三种情况来取得字符块的边界。为了能完整切分字符,边界上下界下标特意各放宽了一个像素
item_cnt = len(vertical) zero_vertical_index = [index for index, value in enumerate(vertical) if value == 0] if 0 not in zero_vertical_index: first_index = 0 last_index = zero_vertical_index[0] + 1 elif item_cnt - 1 not in zero_vertical_index: first_index = zero_vertical_index[0] - 1 last_index = item_cnt - 1 else: target = [index for index, value in enumerate(zero_vertical_index[:-1]) if zero_vertical_index[index + 1] - zero_vertical_index[index] != 1] first_index = zero_vertical_index[target[0]] - 1 last_index = zero_vertical_index[target[-1] + 1] + 1
-
切分字符
image(v_f, v_l) = first_index, last_index target_char = char[v_f: v_l]
-
保存字符。由于前期并没有专门对验证码图片打标,所以在保存的时候需要告诉计算机要保存的字符是什么。另外,观察发现验证码字符的字体和大小基本没有什么变化,所以在这个问题中其实不需要太多的数据集,于是在实际操作中,我只解析了100张验证码(算是偷懒了~)。
imageclass_names = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T','U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'] class_ords = [ord(class_name) for class_name in class_names] class_cnt = {class_name: 0 for class_name in class_names} cv2.imshow('target_char', target_char) flag = cv2.waitKey(0) if flag in class_ords: class_name = class_names[class_ords.index(flag)] class_cnt[class_name] += 1 cv2.imwrite(os.path.join(char_dir, '{}_{}.jpg'.format(class_name, str(class_cnt[class_name]))) , target_patch)
-
后记
至此,整个数据集的预处理到构建基本上就讲完了。
本系列的所有源代码都会放在下面的github仓库里面,有需要可以参考,有问题欢迎指正,谢谢!
https://github.com/TitusWongCN/AutoTokenAppointment
下一步就是激动人心的模型设计与训练啦,敬请期待。
网友评论