这是「进击的Coder」的第 394 篇技术分享

作者:崔庆才

来源:崔庆才丨静觅

之前的文章中其实已经提到过如何使用深度学习来识别滑动验证码缺口,文章见利用 Python 深度学习识别滑动验证码缺口。

之前的案例是网易盾,现在我想在某验的基础上做一些实验,也就是说训练一个可以识别某验滑动验证码缺口的模型。

所以第一步便是准备一些训练素材了,比如类似这样的:

这里就需要把右侧的验证码缺口找出来,比如标注出目标滑块的左侧偏移位置。

所以,要训练深度学习模型,我们就需要很多样例图片对吧,所以像上一篇文章一样,我需要收集一些这样的图片,然后手工标注一些缺口位置,然后用于模型的训练。

不过,存在的一个问题就是,某验的背景图片花样太少了,就那么几种背景图,只是缺口位置变了变,所以它对于训练一个健壮的模型是不太够用的。

于是我就有了一个想法 —— 自己做标注数据。

也就是说我要自己生成一些类似上面的图片,顺便生成的过程就记录下来了目标滑块的位置了,顺便标注数据也就生成了。

思路

先看下最后我生成的效果吧:

就是这样的,这个图是用代码生成的。

其实很简单,这里就是生成一张背景图,然后贴上左侧和右侧的滑块就好了,左侧的就是源滑块,右侧就是缺口,二者的高度是一样的。另外观察下,左侧的滑块是有黑色阴影和黄色内阴影的,右侧的滑块是有黑色内阴影的。

那这个这么生成呢?

往下看。

获取滑块 RGB

首先,在制作之前其实我是不知道滑块的具体像素 RGB 值的,比如目标滑块我看到它似乎是个半透明的样子,还带有一些纹理,而且滑块和背景是融为一体的,我怎么把它抠出来呢?

比如就这张图:

我想单独把滑块和缺口对应的图层抠出来?怎么做到呢?直接抠可能比较难。

不过这里还有另一个信息,那就是我可以通过检查网页源代码拿到无滑块的原图,如图所示:

具体获取方法从源码里面把 CSS 样式改掉就好了:

所以,很自然地,二者像素做差就行了,代码如下:

import cv2
import numpy as npimage1 = cv2.imread('image1.png')
image2 = cv2.imread('image2.png')
sub = image1 - image2
cv2.imwrite('sub.png', sub)

OK,这里我们使用 cv2 把图片读取为 Numpy 数组,然后二者做差即可,结果如下:

可以看到我们就把二者的不同之处做出来了,比如纯黑色的就是完全一致的,带有一些彩色的可能是因为一些像素偏移导致的,当然最明显的就是两个滑块的的像素内容就单独提出来了。

和我们预估的一样,原始滑块就是带有黑色阴影和黄色内阴影,目标缺口就是带有黑色内阴影。

OK,接下来我就简单用 PS 大法把它们抠出来了,最后效果如下:

这里就是一张原始滑块图、一张目标缺口图,这样缺口图就准备好了。

生成验证码

有了缺口图,那怎么生成验证码呢?很简单,随便找点图,然后裁切成想要的大小就好了。

比如这里就有一张图:

我们就用这张图生成验证码,写个算法裁切一下,裁切成想要的大小:

然后再把刚才的两个滑块和缺口图贴上就好了。

那具体裁切的算法这么写呢?比如扁平的图应该以高为基准放缩,然后从横向中间裁切出来,比如竖高的图就以宽为基准方所,然后纵向从中间裁切出来。这里我先收集了几十张背景图,大小各异:

可以看到有长的、有方的、有竖的、有扁的。

裁切算法实现如下:

import cv2
import os
import numpy as np
from loguru import loggerCAPTCHA_WIDTH = 520
CAPTCHA_HEIGHT = 320for root, dirs, files in os.walk('input'):for file in files:image_path = os.path.join(root, file)logger.debug(f'image path {image_path}')image = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)image_height, image_width, image_dim = image.shapeif image_dim == 3:b_channel, g_channel, r_channel = cv2.split(image)alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255image = cv2.merge((b_channel, g_channel, r_channel, alpha_channel))if image_width / image_height > CAPTCHA_WIDTH / CAPTCHA_HEIGHT:image = cv2.resize(image, (int(CAPTCHA_HEIGHT * image_width / image_height), CAPTCHA_HEIGHT))image_height, image_width, _ = image.shapeimage = image[:, int(image_width / 2 - CAPTCHA_WIDTH / 2): int(image_width / 2 + CAPTCHA_WIDTH / 2)]else:image = cv2.resize(image, (CAPTCHA_WIDTH, int(CAPTCHA_WIDTH * image_height / image_width)))image_height, image_width, _ = image.shapeimage = image[int(image_height / 2 - CAPTCHA_HEIGHT / 2): int(image_height / 2 + CAPTCHA_HEIGHT / 2), :]cv2.imwrite(f'output/{file}', image)logger.debug(f'finish output/{file}')

这里就是读取了 input 文件夹下的所有文件,然后根据长宽比进行了裁切,然后将裁切的结果输出到 output 文件夹,裁切结果如下图所示:

合成验证码

好,现在已经有了合适的验证码背景图了,下面就是拼合一下滑块就好了。

滑块图片命名为 block_source.png,目标缺口图片命名为 block_target.png,合成的时候需要注意位置的随机性,比如上下的随机偏移,但也需要控制下滑块的位置,比如源滑块和缺口的高度需要是一直的,缺口应该出现在图片中,而不能跑出去。

最后实现合成算法如下:

import os
from PIL import Image
import random
import glob
from loguru import loggerCAPTCHA_WIDTH = 520
CAPTCHA_HEIGHT = 320image_source = Image.open('block_source.png')
image_target = Image.open('block_target.png')label_offset_x_base = 260
label_offset_y_base = 120count = 0
total = 1000
root_dir = 'output'
file_paths = glob.glob(f'{root_dir}/*.png')while True:file_path = random.choice(file_paths)offset_y = random.randint(-100, 100)offset_x = random.randint(-100, 100)label_offset_x = label_offset_x_base + offset_xlabel_offset_y = label_offset_y_base + offset_yimage_path = os.path.join(file_path)image = Image.open(image_path)image.paste(image_target, (offset_x, offset_y), image_target)image.paste(image_source, (0, offset_y), image_source)label = f'0 {label_offset_x / CAPTCHA_WIDTH} {label_offset_y / CAPTCHA_HEIGHT} 0.16596774 0.24170968'image.save(f'captcha/images/captcha_{count}.png')logger.debug(f'generated captcha file captcha_{count}.png')with open(f'captcha/labels/captcha_{count}.txt', 'w') as f:f.write(label)logger.debug(f'generated label file captcha_{count}.txt')count += 1if count > total:logger.debug('finished')break

这里设定了生成 1000 张图片,然后通过 offset_y 和 offset_x 来控制目标缺口的位置,读取图片之后,通过 image 的 paste 方法指定对应的位置即可,标注结果根据偏移的像素值自行计算。

最后生成到 captcha 文件夹里,images 就是验证码图,labels 就是标注结果,如图所示:

样例验证码如图所示:

这样,背景图片足够丰富,那就足够支撑训练验证码识别模型了,模型也会更加健壮。

训练结果

具体的训练结果我就不赘述了,大家可以参考 https://github.com/Python3WebSpider/DeepLearningImageCaptcha2。

看下模型识别结果:

识别准确率很高,可以完美把想要的缺口标注出来,大功告成。

后记

另外发现缺口的形状也对识别效果有一定的影响,所以滑块和缺口图片也需要多弄几种类型,使模型更加健壮。

End

「进击的Coder」专属学习群已正式成立,搜索「CQCcqc4」添加崔庆才的个人微信或者扫描下方二维码拉您入群交流学习。

看完记得关注@进击的Coder

及时收看更多好文

↓↓↓

增强版!如何深度学习识别滑动验证码缺口相关推荐

  1. 深度学习识别滑动验证码缺口

    1. 准备工作 同样地,本节还是主要侧重于完成利用深度学习模型来识别验证码缺口的过程,所以不会侧重于讲解深度学习模型的算法,另外由于整个模型实现较为复杂,本节也不会从零开始编写代码,而是倾向于把代码提 ...

  2. 利用深度学习识别滑动验证码缺口位置

    做爬虫的同学肯定或多或少会为验证码苦恼过,在最初的时候,大部分验证码都是图形验证码.但是前几年「极验」验证码横空出世,行为验证码变得越来越流行,其中之一的形式便是滑块验证码. 滑块验证码是怎样的呢?如 ...

  3. 验证码识别 java 深度学习_使用深度学习识别验证码注解

    前言 在抓取一些网站的时候难免会遇到一些验证码.想起去年接触过一段时间的验证码识别技术,所以把之前使用的开源的cnn识别再拿出来做个注解.加深理解,也方便以后的使用.希望能对大家有所帮助! 正文 网上 ...

  4. python 训练识别验证码_python使用tensorflow深度学习识别验证码

    本文介绍了python使用tensorflow深度学习识别验证码 ,分享给大家,具体如下: 除了传统的PIL包处理图片,然后用pytessert+OCR识别意外,还可以使用tessorflow训练来识 ...

  5. 利用深度学习(CNN)进行验证码(字母+数字)识别

    利用深度学习(CNN)进行验证码(字母+数字)识别_helen1313的专栏-CSDN博客 本文方法针对的验证码为定长验证码,不包含中文. 本文的思路是:1. 使用keras中预训练好的模型,在pyt ...

  6. 利用深度学习识别番茄早期植株中的塔图绝对菌

    利用深度学习识别番茄早期植株中的塔图绝对菌 1.研究内容 提出了一种深入学习的方法来识别番茄斑潜蝇害虫(塔图绝对)的入侵.卷积神经网络体系结构(VGG16.VGG19和ResNet50)用于训练分类器 ...

  7. 基于Anaconda安装GPU版PyTorch深度学习开发环境

    基于Anaconda安装GPU版PyTorch深度学习开发环境 1 安装Anaconda 2 安装GPU计算驱动 2.1 检查是否有合适的GPU 2.2 下载CUDA和cuDNN 2.3 安装CUDA ...

  8. MINIST深度学习识别:python全连接神经网络和pytorch LeNet CNN网络训练实现及比较(三)...

    版权声明:本文为博主原创文章,欢迎转载,并请注明出处.联系方式:460356155@qq.com 在前两篇文章MINIST深度学习识别:python全连接神经网络和pytorch LeNet CNN网 ...

  9. 利用深度学习进行交通灯识别_通过深度学习识别交通信号灯

    利用深度学习进行交通灯识别 by David Brailovsky 戴维·布雷洛夫斯基(David Brailovsky) 通过深度学习识别交通信号灯 (Recognizing Traffic Lig ...

最新文章

  1. debian linux忘记密码,debian ubuntu linux 忘记root密码的重置方法
  2. 李飞飞AI100报告提出14大AI机遇与挑战(附pdf)
  3. C语言——第0次作业(二)
  4. 【深度学习入门到精通系列】模型结构可视化神器Netron(连.pth都可以~!)
  5. SVN不是配置管理系统
  6. 采购订单单位与基本计量单位不一致问题案例
  7. 如何在.NET上处理二维码
  8. tf.slice解析
  9. centos 7 快速安装nginx
  10. linux系统安全加固基础篇1
  11. 修改win10服务器登录密码,玩转Win10密码基础篇:设置修改系统登录密码
  12. Python项目实战:使用selenium爬取拉勾网数据
  13. GeForce GTX 1050-2G驱动安装
  14. Qt其实时报:一下插件错误无法被载入
  15. 获得新成就1024勋章
  16. 光纤通信工程-波分复用DWDM(十一)
  17. 进程上下文与线程上下文
  18. 18章 资产收益率和风险
  19. 安搭Share:三星接班人李在镕或成韩方最富股东,持有票市值近百亿美元
  20. Storm学习一集群安装

热门文章

  1. 多触点电器自动测试系统
  2. 理工科研究生论文致谢频用诗词,导师:摘要都写不通你还敢搞文学?
  3. 盒饭官方网站服务器,魔兽世界怀旧服:TAQ团本是否便当?半数服务器开门,只等首通了...
  4. 哪种数据库隔离级别能防止脏读?(多选题)
  5. linux源添加几个,Linux下添加源的几种方法
  6. 【自用】谷歌浏览器百度(阿里)网盘在线倍速播放
  7. c语言编译器被vac,csgovac被屏蔽 CSGOVAC系统被屏蔽解决方法
  8. mvn dependency:tree查看jar包间接依赖
  9. 人情事故还是人情世故?
  10. 计算机网络技术系训口号,*训霸气押韵口号大全