使用深度学习实现滑动验证码识别初探

主要目标检测算法:
       在视觉领域,使用卷积神经网络来实现物体的分类与识别能更好的反映和抽取出物体的特征,因而被大规模的应用在这些任务上面。
       为了解决在一个图像中检测多个对象的问题,有研究者提出了RCNN(Regions with CNN features)的概念,并实现其算法;后来又发展出了FAST-RCNN ,FASTER-RCNN, FCN 这些更高阶的算法。
       FAST RCNN 通过先将整幅图片进行卷积,得到特征图,再将某一层的特征图作ROI POOLING,接着输入给FCs(全连接网络),最后再输出分类用的softmax层和四个坐标的回归。
由于将各种分类都用到的卷积操作在开始就首先统一运算了一遍,效率大为提高。而Yolo系列的目标检测算法更为先进,特点是速度快 效果好 部署方便。属于一步实现。

YOLO算法简介:

       在进行对象的位置检测以及分类方面,深度神经网络YOLO算法应用效果很好,本文就医yolo来实现,它的主要特点是速度够快,而且准确率也很高,采用直接预测目标对象的边界框的方法,将候选区和对象识别这两个阶段合二为一,与faster rcnn区分开来,是一流的检测方法。
Yolo算法不再是窗口滑动,而是直接将原始图片分割成互不重合的小方块,然后通过卷积最后生产各样大小的特征图,可以认为特征图的每个元素是对应原始图片的一个小方块,然后用每个元素来可以预测那些中心点在该小方格内的目标,这就是Yolo算法的主要思想。
       YOLO 一代包含有全连接层,从而能直接预测 Bounding Boxes 的坐标值。 Faster R-CNN 的方法只用卷积层与 Region Proposal Network 来预测 Anchor Box 偏移值与置信度,而不是直接预测坐标值。作者发现通过预测偏移量而不是坐标值能够简化问题,让神经网络学习起来更容易,所以最终 YOLO 去掉了全连接层,使用 Anchor Boxes 来预测 Bounding Boxes。
Yolo网络结构:
        YOLO采用卷积神经网络进行预测,YOLO的整个结构就是输入图片经过神经网络的变换得到一个输出的张量 。 步骤如下:
       (1)将输入图像调整为448×448,(2)在图像 上运行单个卷积网络,(3)由模型的置信度对所得到的检测进行阈值处理。
       首先,YOLO速度非常快。由于我们将检测视为回归问题,所以不需要复杂的流程。测试时在一张新图像 上简单的运行我们的神经网络来预测。
       其次,YOLO在进行预测时,会对图像进行全面地推理。与基于滑动窗口和区域提出的技术不同,YOLO在训练期间和测试时会看到整个图像,所以它隐式地编码了。
       关于类的上下文信息,快速R-CNN是一种顶级的检测方法,但是它看不到更大的上下文信息,所以在图像中会将背景块误检为目标。与快速R-CNN相比,YOLO的背景误检数量少了一半。
然后,由于YOLO具有高度泛化能力,它被利用在很多目标检测场合。YOLO的一个贡献是将检测问题转化为了回归问题,之前faster RCNN是先分两步,先提取region proposal,也就是判断是前景还是背景的问题,之后再分类,具体看前景是什么东西。而YOLO直接通过regression一次既产生坐标,又产生每种类别的概率。YOLO的特点在于快,其中一方面来源于regression机制,还有一个原因就在于region proposal的提取过程了。网络使用一个 Logistic Activation 来对于网络预测结果进行限制,让结果介于 0 到 1 之间, 因为使用了限制让数值变得参数化,也让网络更容易学习、更稳定。

YOLOV3
       YOLO3比于之前的yolo1和yolo2主要的改进有:调整了网络结构;增加了多尺度检测;对象分类用Logistic取代了softmax。这样能够支持多标签对象(比如一个人有Woman 和 Person两个标签)。以及更深的网络结构darknet53,还有某些细节上的变动。
多尺度检测:
       对于多尺度检测来说,采用多个尺度进行预测,具体形式是在网络预测的最后某些层进行上采样拼接的操作来达到;对于分辨率对预测的影响如下:
       分辨率信息直接反映的就是构成object的像素的数量。一个object,像素数量越多,它对object的细节表现就越丰富越具体,也就是说分辨率信息越丰富。这也就是为什么大尺度feature map提供的是分辨率信息了。语义信息在目标检测中指的是让object区分于背景的信息,即语义信息是让你知道这个是object,其余是背景。在不同类别中语义信息并不需要很多细节信息,分辨率信息大,反而会降低语义信息,因此小尺度feature map在提供必要的分辨率信息下语义信息会提供的更好。(而对于小目标,小尺度feature map无法提供必要的分辨率信息,所以还需结合大尺度的feature map)
三个尺度特征层
       YOLO3更进一步采用了3个不同尺度的特征图来进行对象检测。能够检测的到更加细粒度的特征。网络的最终输出有3个尺度。在第79层之后经过几个卷积操作得到的是1/32 (13*13) 的预测结果,下采样倍数高,这里特征图的感受野比较大,因此适合检测图像中尺寸比较大的对象。
然后这个结果通过上采样与第61层的结果进行concat,再经过几个卷积操作得到1/16的预测结果;它具有中等尺度的感受野,适合检测中等尺度的对象。91层的结果经过上采样之后在于第36层的结果进行concat,经过几个卷积操作之后得到的是1/8的结果,它的感受野最小,适合检测小尺寸的对象。concat:张量拼接。将darknet中间层和后面的某一层的上采样进行拼接。拼接的操作和残差层add的操作是不一样的,拼接会扩充张量的维度,而add只是直接相加不会导致张量维度的改变。

使用Kmeans聚类的方法来决定anchors的尺寸大小:
       YOLO2已经开始采用K-means聚类得到先验框的尺寸,YOLO3延续了这种方法,为每种下采样尺度设定3种先验框,总共聚类出9种尺寸的先验框。在COCO数据集这9个先验框是:(10x13),(16x30),(33x23),(30x61),(62x45),(59x119),(116x90),(156x198),(373x326)。分配上,在最小的1313特征图上(有最大的感受野)应用较大的先验框(116x90),(156x198),(373x326),适合检测较大的对象。中等的2626特征图上(中等感受野)应用中等的先验框(30x61),(62x45),(59x119),适合检测中等大小的对象。较大的52*52特征图上(较小的感受野)应用较小的先验框(10x13),(16x30),(33x23),适合检测较小的对象。

       yolo v3对bbox进行预测的时候,采用了logistic regression。yolo v3每次对b-box进行predict时,输出和v2一样都是(tx,ty,tw,th,to)​ ,然后通过公式1计算出绝对的(x, y, w, h, c)。logistic回归用于对anchor包围的部分进行一个目标性评分(objectness score),(用于NMS),即这块位置是目标的可能性有多大。
公式一:

       yolo_v3只会对1个prior进行操作,也就是那个最佳prior。而logistic回归就是用来从9个anchor priors中找到objectness score(目标存在可能性得分)最高的那一个。

YoloV3网络实现
       一, 网络整体流程
       1,网络resnet的思想
       1,主干网络修改为darknet53,其重要特点是加入了残差卷积网络,每当通过这个卷积层之后图像的尺寸就会减小到一半,而通道数变大,提取相应特征。
darknet53中的残差卷积网络就是首先进行一次3X3、步长为2的卷积,然后进行若干次残差结构的堆叠,每个残差模块由两个卷积层和一个shortcut connections组成,即进行一次1X1的卷积和一次3X3的卷积,并把这个结果加上初始的输入作为最后的结果。 1,2,8,8,4代表有几个重复的残差模块。残差网络的特点是容易优化,并且能够通过增加相当的深度来提高准确率。其内部的残差块使用了跳跃连接,缓解了在深度神经网络中的层次深带来的梯度消失问题。

       2、darknet53的每一个卷积层部分使用了特有的DarknetConv2D结构,每一次卷积的同时进行l2正则化,完成卷积后进行BatchNormalization标准化与LeakyReLU。普通的ReLU是将所有的负值都设为零,Leaky ReLU则是给所有负值赋予一个非零斜率。

  吗    3,整个v3结构里面,没有池化层和全连接层,网络的下采样都是通过设置卷积的stride来达到的,每个残差模块之后又要加上一个zero padding,

网络结构代码对应net文件下的darknet.py
        2、从特征获取预测结果
       1、在特征利用部分,yolo3提取多特征层进行目标检测,一共提取三个特征层,三个特征层位于主干部分darknet53的不同位置,分别位于中间层,中下层,底层,三个特征层的shape分别为(52,52,256)、(26,26,512)、(13,13,1024)。
       2、三个特征层进行5次卷积处理,处理完后一部分用于输出该特征层对应的预测结果,一部分用于进行反卷积UmSampling2d后与其它特征层进行结合。
       3、输出层的shape分别为(13,13,75),(26,26,75),(52,52,75),最后一个维度为75是因为该图是基于voc数据集的,它的类为20种,yolo3针对每一个特征层存在3个先验框,所以最后维度为3x25;如果是coco数据集,类则为80种,最后的维度应该为255 = 3x85,三个特征层的shape为(13,13,255),(26,26,255),(52,52,255)
       4、对于实际项目最后一个维度的大小取决于实际分类类别,算法一致。
       5、其实际情况就是,由于使用的是Pytorch,它的通道数默认在第一位,输入N张416x416的图片,在经过多层的运算后,会输出三个特征层shape分别为(N,255,13,13),(N,255,26,26),(N,255,52,52)的数据,对应每个图分为13x13、26x26、52x52的网格上3个先验框的位置。
3、预测结果的解码及其处理
        由第二步我们可以获得三个特征层的预测结果,shape分别为(N,255,13,13),(N,255,26,26),(N,255,52,52)的数据,对应每个图分为13x13、26x26、52x52的网格上3个预测框的位置。但是这个预测结果并不对应着最终的预测框在图片上的位置,还需要解码才可以完成。
此处要讲一下yolo3的预测原理,yolo3的3个特征层分别将整幅图分为13x13、26x26、52x52的网格,每个网络点负责一个区域的检测。我们知道特征层的预测结果对应着三个预测框的位置,我们先将其reshape一下,其结果为(N,3,85,13,13,3,85),(N,3,85,26,26),(N,3,85,52,52)。维度中的85包含了4+1+80,分别代表x_offset、y_offset、h和w、置信度、各分类结果概率。yolo3的解码过程就是将每个网格点加上它对应的x_offset和y_offset,加完后的结果就是预测框的中心,然后再利用 先验框和h、w结合 计算出预测框的长和宽。这样就能得到整个预测框的位置了。
代码对应utils.py种的class DecodeBox(nn.Module):

        当然得到最终的预测结果后还要进行得分排序与非极大抑制筛选
       这一部分基本上是所有目标检测通用的部分。不过该项目的处理方式与其它项目不同。其对于每一个类进行判别。
       首先对每一个如1313上的块对应的预测框上面的预测参数取后面纯类别概率的部分进行最大值运算得到对应的最大可能物体及其概率
class_conf, class_pred = torch.max(image_pred[:, 5:5 + num_classes], 1, keepdim=True)
然后 利用置信度进行第一轮筛选,对象概率
有物体置信度的得分大于某个阈值,将这样的框保留下来,不大于说明连最大可能的物体都不包含,所以这样的框应舍弃。
(score = 某个对象的概率 * 置信度)

       conf_mask = (image_pred[:, 4] * class_conf[:, 0] >= conf_thres).squeeze()

       最后在最终的所有框里面依据每一个类别取出这一类置信度最高的,一步一步往下判断,判断重合程度是否大于nms_thres,如果是则去除掉,便能得到这一个对象周围最接近它的框。
for c in unique_labels:

 
 
  1. #------------------------------------------#
  2. # 获得某一类得分筛选后全部的预测结果
  3. #------------------------------------------#
  4. detections_class = detections[detections[:, -1] == c]
  5. # 使用官方自带的非极大抑制会速度更快一些!
  6. #------------------------------------------#
  7. keep = nms(
  8. detections_class[:, :4],
  9. detections_class[:, 4] * detections_class[:, 5],
  10. nms_thres
  11. )
  12. max_detections = detections_class[keep]

       NMS内部原理就是通过打分来选出最好的结果,与这个结果重叠的对象去掉,是一个不断迭代的过程。
具体的过程是:
       1,设置一个分数阈值,低于的直接置为0;
       2,遍历对于每个对象:
选出分数最高的那个及其bounding box放到输出列表中;
将其他的与上面选出的分数最高的那个计算IOU,设置一个阈值,大于阈值的表示重叠度较高,把分数置为0;如果所有的bounding box都在输出列表 中或者分数为0,那么这个对象的NMS就结束
对接下来的对象执行此过程
       3.得出输出结果
二、训练部分
       训练中采用了drop out和数据增强(data augmentation)来防止过拟合
get_random_data(annotation_line, input_shape, random=True, max_boxes=20, jitter=.3, hue=.1, sat=1.5, val=1.5, proc_img=True):

       1、计算loss所需参数
在计算loss的时候,计算的是pred(网络的预测结果)和target(网络的真实框情况)之间的对比:

       2、loss的计算过程
       拿到pred和target后,不可以简单的减一下作为对比,需要进行如下步骤。
       1.判断真实框在图片中的位置,判断其属于哪一个网格点去检测。
       2.判断真实框和哪个先验框重合程度最高。
       3.计算该网格点应该有怎么样的预测结果才能获得真实框
       4.对所有真实框进行如上处理。
       5.获得网络应该有的预测结果,将其与实际的预测结果对比。

3,YOLO的LOSS函数
       yolov3 中定义的Loss函数如上,基本可以看出,对于宽高回归预测的部分是采用mse均方差来进行的,对于分类部分和置信度是采用BCELoss来进行的,最后把各种Loss相加得出最终的loss
def MSELoss(pred,target):
return (pred-target)*2
def BCELoss(pred,target):
epsilon = 1e-7
pred = clip_by_tensor(pred, epsilon, 1.0 - epsilon)
output = -target 
torch.log(pred) - (1.0 - target) * torch.log(1.0 - pred)
return output

训练YOLOV3模型
       本文使用VOC格式进行训练。
       训练前将标签文件放在VOCdevkit文件夹下的VOC2007文件夹下的Annotation中。
       训练前将图片文件放在VOCdevkit文件夹下的VOC2007文件夹下的JPEGImages中。
       在训练前利用voc2yolo3.py文件生成对应的txt。

       再运行根目录下的voc_annotation.py,运行前需要将classes改成你自己的classes。classes =[“huakuaiz”,”huakuaiy”]

       之后就会生成对应的2007_train.txt,每一行对应其图片位置及其真实框的位置。

       在训练前修改model_data里面的voc_classes.txt文件,将classes设为huakuaiz
huakuaiy两个classes。同时还需要修改utils/config.py文件,修改内部的Num_Classes变成所分的 种类的数量2。在train.py 中设置载入的预训练文件model_path = “model_data/yolo_weights.pth”
运行train.py即可开始训练。

Python 3.8.5 (default, Sep 3 2020, 21:29:08) [MSC v.1916 64 bit (AMD64)]
Type “copyright”, “credits” or “license” for more information.
IPython 7.19.0 — An enhanced Interactive Python.
runfile(‘C:/Users/Administrator/yolov3_2/train.py’, wdir=’C:/Users/Administrator/yolov3_2’)
滑动验证码操作
在屏幕上取到相应位置的坐标 (yolov3_2_zhuadianzuobiao.py):
screenWidth, screenHeight = pyautogui.size()
currentMouseX, currentMouseY = pyautogui.position()
print(currentMouseX, currentMouseY )
接着在yolov3_2_webdriver.py中:
移动到这个坐标位置,点击,显示输入账号密码框输入相应字符
location = img.location
x1, y1 = location[“x”], location[“y”] # 根据图片获取到的位置之后取其相应的x,y值
x2, y2 = location[“x”] + size[“width”], location[“y”] + size[“height”]
captcha = screen_shot.crop((int(x1), int(y1), int(x2), int(y2))) # 截获区域图片
captcha.save(image_file_name)
return captcha
self.driver.find_element_by_xpath(“//input[@placeholder=’账号’]”).send_keys(self.user_name) #找到账号输入框并输入账号

self.driver.find_element_by_class_name(“account”).send_keys(self.user_name)

self.driver.find_element_by_xpath(“//input[@placeholder=’密码’]”).send_keys(self.pass_wrod) #找到密码框并输入密码
点击登录,弹出滑块 , 截图 ,保存 :
pyautogui.moveTo(1331 ,654)
time.sleep(1.5)
pyautogui.click() # 点击登陆 弹出滑块验证码
time.sleep(2)
image1 = self.crop_image(“captcha1.png”) # 截取验证码图片
image = Image.open(‘captcha1.png’) # 打开截取的图片
输入预测网络 给出 滑块位置
lstz= yolo.detect_image(image) # 调用yolo图片预测函数
相减得到偏移量
mubiaozbx=(right1+left1)/2-(right0+left0)/2
最后滑动实现
实际效果
经验证,实际操作中可以实现验证码的识别和自动滑动,说明深度学习的方法是可行的

猜你喜欢

转载自blog.csdn.net/weixin_44906759/article/details/128074018