发布时间:2025-03-29 21:38:07编辑:123阅读(90)
目标检测
识别滑动验证码的目标缺口问题,其实可以归结为目标检测问题。什么叫目标检测?顾名思义就是把想找的东西找出来,也就是找图片缺口位置。现在比较流行的目标检测算法有R-CNN,Fast R-CNN,Faster R-CNN,SSD,YOLO等。
目前目标检测算法主要有两种实现方法,一阶段式和二阶段式。
一阶段式(One stage):不需要产生候选框,直接将目标的定位和分类问题转化为回归问题,俗称“看一眼”,使用这种实现的算法有YOLO和SSD,这种方法虽然正确率不及Two Stage,但架构相对简单,检测速度更快。
二阶段式(Two Stage):算法首先生成一系列目标所在位置的候选框,再对这些候选出来的结果进行样本分类,即先找出来在哪儿,再分出来是啥,俗称“看两眼”,使用这种实现的算法有R-CNN,Fast R-CNN,Faster R-CNN等,这种方法架构相对复杂,但正确率高。
选用YOLO算法实现对滑动验证码缺口的识别。YOLO的英文全称是You Only Look Once,目前的最新版本是V5,应用比较广泛的版本是V3。
数据准备
训练深度学习模型需要准备训练数据。这里的数据也分两部分,一部分是验证码图片,另一部分是标注数据。这次的数据标注不再是单纯的验证码文本,而是缺口位置,缺口对应一个矩形框,要表示矩形框,至少需要4个数据,如矩形左上角的点的纵横坐标下x,y加上矩形的宽高w,h。
明确了数据是什么,接下来就准备。第一步是收集验证码图片,第二步是标注图片中的缺口位置并转化为想要的4位数字。打开网站https://passport.jd.com/new/login.aspx,点击“登录”按钮就会弹出一个滑动验证码。
手工截图肯定不可靠,因为要收集的图片量非常大,这么做不仅费时费力,还不好准确地定位边界,会导致保存下来的图片有大有小。写一个脚本实现自动化裁切和保存。
import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.common.exceptions import WebDriverException from loguru import logger COUNT = 100 for i in range(0, COUNT + 1): try: browser = webdriver.Chrome() browser.get('https://passport.jd.com/new/login.aspx') browser.implicitly_wait(30) # 账户 browser.find_element(By.ID, 'loginname').send_keys('username') time.sleep(0.3) # 密码 browser.find_element(By.ID, 'nloginpwd').send_keys('password') time.sleep(0.2) # 登录 browser.find_element(By.ID, 'loginsubmit').click() time.sleep(0.5) # 下载图片 img_dir_name = f'D:\PythonProject_deep_learning_slide_verification\images\captcha_{i}.png' captcha = browser.find_element(By.XPATH,'//div[@class="JDJRV-bigimg"]/img').screenshot(img_dir_name) except WebDriverException as e: logger.error(f'webdriver error occurred {e.msg}') finally: browser.close()
代码逻辑先是一个for循环,循环次数为count,每次循环都使用selenium启动一个浏览器,然后打开目标网站,模拟点击登录按钮的操作触发验证码弹出,然后截取验证码对应的节点,再调用screenshot方法保存下来。
运行完后,目录下会有非常多的图片。
第一步完成,接下来完成第二步,准备数据标注,这里推荐使用的工具是labelImg,使用pip直接可以安装
pip install labelImg
安装完后在命令行直接运行 labelImg
点击左侧的Open Dir 按钮打开刚刚下载的images目录,然后点击左下角的Create RectBox创建一个标注框,可以将缺口所在的矩形框框起来,框完后labelImg会弹出填写保存名称的提示框,填写target,然后点击ok按钮
这时会发现本地保存了一个xml文件,内容如下:
<annotation> <folder>images</folder> <filename>captcha_0.png</filename> <path>D:\PythonProject_deep_learning_slide_verification\images\captcha_0.png</path> <source> <database>Unknown</database> </source> <size> <width>343</width> <height>133</height> <depth>3</depth> </size> <segmented>0</segmented> <object> <name>target</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>172</xmin> <ymin>28</ymin> <xmax>220</xmax> <ymax>76</ymax> </bndbox> </object> </annotation>
从中可以看到,size节点里有三个节点,分别是width,height,depth,代表原验证码图片的宽度,高度和通道数。object节点下的bndbox节点包含标注的缺口位置,通过观察对比可以直到xmin,ymin指的是左上角的坐标,xmax,ymax指的是右下角的坐标。
使用下面的方法简单做一下数据处理:
import xmltodict import json import os xml_path = os.path.join(os.getcwd(), 'annotation_images') txt_path = os.path.join(os.getcwd(), 'labels') def parse_xml(file): xml_str = open(file, mode='r', encoding='utf-8').read() data = xmltodict.parse(xml_str) data = json.loads(json.dumps(data)) annotation = data.get('annotation') width = int(annotation.get('size').get('width')) height = int(annotation.get('size').get('height')) bndbox = annotation.get('object').get('bndbox') box_xmin = int(bndbox.get('xmin')) box_xmax = int(bndbox.get('xmax')) box_ymin = int(bndbox.get('ymin')) box_ymax = int(bndbox.get('ymax')) # 计算中心点坐标和宽高 x_center = (box_xmin + box_xmax) / 2.0 y_center = (box_ymin + box_ymax) / 2.0 box_width = box_xmax - box_xmin box_height = box_ymax - box_ymin # 归一化处理 x_center /= width y_center /= height box_width /= width box_height /= height print(x_center, y_center, box_width, box_height) return x_center, y_center, box_width, box_height def main(): current_directory = xml_path files = [] for root, dirs, filenames in os.walk(current_directory): for file in filenames: if os.path.isfile(os.path.join(root, file)): files.append(os.path.join(root, file)) return files files = main() for img_path in files: file_name = os.path.basename(img_path).split('.')[0] box_xmin, box_ymin, box_width, box_height = parse_xml(img_path) with open(os.path.join(txt_path, file_name + '.txt'), 'w', encoding='utf-8') as f: f.write(" ".join([str(0), str(box_xmin), str(box_ymin), str(box_width), str(box_height)]))
运行上面代码,结果如下:
其中每一个txt文件各对应一张验证码图片的标注结果,文件内容类似这样:
0 0.5714285714285714 0.39097744360902253 0.13994169096209913 0.3609022556390977
第一位0代表标注目标的索引,由于这里只需要检测一个缺口,所以索引就是0;第二位和第三位代表缺口左上角的点在验证码图片中所处的位置,例如0.5714285714285714代表从横向看,缺口左上角的点大约位于验证码的57%处,至此数据准备阶段完成。
为了达到更好的训练效果,还需要下载一些预训练模型,预训练的意思是已经有一个提前训练好的基础模型了。直接使用预训练模型中的权重文件,就不用从零开始训练模型了,只需要基于之前的模型进行微调即可,这样既节省训练时间,又能达到比较好的效果。
使用YOLO5训练滑动验证缺口验证码
环境安装(wsl环境安装,可参考https://www.py3study.com/Article/details/id/20089.html# wsl安装):
git clone https://github.com/ultralytics/yolov5
cd yolov5
pip install -r requirements.txt
目录结构
slide_ver/
├── images
│ └── slide # 带缺口的原图
└── labels
└── slide # 经过labelImg标注处理过的yolo数据集格式
YOLO的数据集格式
cd /yolo/yolov5/data
vim sliding.yaml
path: ../datasets/slide_ver # 目录 train: images/slide # 训练集 val: images/slide # 验证集 nc: 1 # 类别数量 names: ['slideing'] # 类别名:避免用中文
把对应的数据拷进对应的目录,修改train.py,如下:
保存,运行。
python train.py
训练完成.
信息中的参数是介绍:
Epoch 训练轮数
gpu_mem gpu占用内存
box 边界框损失 YOLO V5使用 GIOU Loss作为bounding box的损失,Box推测为GIoU损失函数均值,越小方框越准;
obj 目标检测损失 推测为目标检测loss均值,越小目标检测越准;
cls 分类损失 推测为分类loss均值,越小分类越准;(缺口只有一个类别所以为0没有浮动)
img_size 图片尺寸默认为640
Images 测试集图片个数849张
Labels 测试集标签个数847张
P 精度
R 召回率
一般训练结果主要观察精度和召回率波动情况
看一下测试集的预测效果:
cd /yolo/yolov5/runs/train/slideing
打开val_batch0_labels.jpg
最重要的是在weights目录下有两个pt模型
最好的模型,和最后的模型,之后验证就可以用着模型进行验证.
验证模型
把需要测试的图片放到对应的目录
在detect.py文件中配置可以对模型进行检测
运行detect.py
到对应的目录查看效果,如下:
yolo有接口测试就在utils下的flask_rest_api文件中restapi.py是服务端,example_requset.py是客户端。
pip install flask
python restapi.py --port 5000
客户端访问:
import requests import os DETECTION_URL = "http://127.0.0.1:5000/v1/object-detection/yolov5s" IMAGE = os.path.join(os.getcwd(), 'verify_images/captcha_0.png') # Read image with open(IMAGE, "rb") as f: image_data = f.read() response = requests.post(DETECTION_URL, files={"image": image_data}).json() print(response)
[{'xmin': 91.528755188, 'ymin': 4.3374404907, 'xmax': 140.5720062256, 'ymax': 45.5197601318, 'confidence': 0.6900528669, 'class': 14, 'name': 'bird'}]
上一篇: Ai之大模型-公开数据集-理论6.2
下一篇: 没有了
48317
47118
37990
35284
29777
26464
25402
20398
20089
18535
90°
92°
98°
168°
138°
359°
207°
189°
242°
403°