YOLOv5入门与滑动验证码位置识别实战
YOLOv5入门与滑动验证码位置识别实战
滑动验证码是常见的网站安全验证手段,而YOLOv5作为当前主流的目标检测算法,能够快速准确地识别出验证码中的空缺位置。本文将详细介绍如何使用YOLOv5完成滑动验证码位置识别的实战项目,包括环境配置、数据准备、标注、训练和验证等关键步骤。
前言
YOLO(You Only Look Once)是大名鼎鼎的目标检测算法,其核心思想是一次性完成目标检测任务,相比传统的滑动窗口方法具有显著的性能优势。本文基于YOLO的稳定版本v5进行实验,成功实现了滑动验证码空缺位置的识别任务。在有限的数据集上,模型取得了令人满意的效果。本文将重点介绍实践应用部分,对于算法原理感兴趣的读者可以参考其他资料。
环境配置
- Python版本:3.9.13
- 操作系统:Windows 10
- CPU:R7-7840HS
- GPU:无(使用集成显卡)
YOLOv5安装
下载源码
git clone https://github.com/ultralytics/yolov5.git
模型选择
本次实验选用YOLOv5s模型,该模型体积适中且效果良好。更多模型可以在官方仓库中下载:
安装依赖库
pip install -r requirements.txt
数据准备
从网易易盾行为式验证码手动下载30张滑动验证码图片。为了获得更准确的结果,建议增加训练集的图片数量。有能力的读者也可以编写脚本自动下载图片。
数据标注
使用开源工具Labelme进行数据标注,具体地址如下:
- Labelme官方仓库
- Labelme下载地址
使用Labelme标注每个验证码缺口的位置,并将其命名为"target"。标注完成后,每张图片会生成一个包含标注框和原始图像内容的JSON文件。
标注转换
Labelme生成的JSON文件需要转换为YOLOv5可识别的格式。以下是转换脚本,该脚本会将当前目录下的所有JSON文件转换为训练所需的格式,并按80%的比例划分训练集和验证集。
import os
import json
import random
import base64
from glob import glob
dic_labels = {'target': 0, 'ratio': 0.8}
def generate_labels(dic_labs):
ratio = dic_labs['ratio']
for index, labelme_annotation_path in enumerate(glob(f'imgs/*.json')):
image_id = os.path.basename(labelme_annotation_path).rstrip('.json')
train_or_valid = 'train' if random.random() < ratio else 'valid'
labelme_annotation_file = open(labelme_annotation_path, 'r')
labelme_annotation = json.load(labelme_annotation_file)
yolo_annotation_path = os.path.join(train_or_valid, 'labels', image_id + '.txt')
yolo_annotation_file = open(yolo_annotation_path, 'w')
yolo_image = base64.decodebytes(labelme_annotation['imageData'].encode())
yolo_image_path = os.path.join(train_or_valid, 'images', image_id + '.jpg')
yolo_image_file = open(yolo_image_path, 'wb')
yolo_image_file.write(yolo_image)
yolo_image_file.close()
for shape in labelme_annotation['shapes']:
if shape['shape_type'] != 'rectangle':
print(f'Invalid type `{shape["shape_type"]}` in annotation `annotation_path`')
continue
points = shape['points']
scale_width = 1.0 / labelme_annotation['imageWidth']
scale_height = 1.0 / labelme_annotation['imageHeight']
width = (points[1][0] - points[0][0]) * scale_width
height = (points[1][1] - points[0][1]) * scale_height
x = ((points[1][0] + points[0][0]) / 2) * scale_width
y = ((points[1][1] + points[0][1]) / 2) * scale_height
object_class = dic_labels[shape['label']]
yolo_annotation_file.write(f'{object_class} {x} {y} {width} {height}\n')
yolo_annotation_file.close()
print("creat lab %d : %s" % (index, image_id))
if __name__ == "__main__":
os.makedirs(os.path.join("train", 'images'), exist_ok=True)
os.makedirs(os.path.join("train", 'labels'), exist_ok=True)
os.makedirs(os.path.join("valid", 'images'), exist_ok=True)
os.makedirs(os.path.join("valid", 'labels'), exist_ok=True)
generate_labels(dic_labels)
训练配置
在YOLOv5目录下找到train.py
文件,需要修改以下参数:
- 第516行
--weights
:配置预训练模型路径,值为yolov5s.pt
- 第518行
--data
:配置数据集文件路径,值为data/imgs.yaml
- 第522行
--imgsz
:配置图片尺寸,值为320 - 第537行
--device
:配置运行设备,值为cpu
(有GPU的用户可以设置相应的显卡号)
imgs.yaml
文件内容如下:
train: ../train/
val: ../valid/
test:
nc: 1
names: ['target']
开始训练
在终端中运行以下命令开始训练:
python train.py
训练完成后,会在根目录生成一个runs
目录,其中train
文件夹下的exp*
就是训练结果。我们找到最后一个exp20
文件夹下的weights
目录,其中best.pt
代表最好的结果,last.pt
表示最后一次迭代的结果。
验证结果
使用以下命令验证模型效果:
python detect.py --weights best.pt --source ../imgs --data data/imgs.yaml --imgsz [160,320] --conf-thres 0.15
参数说明:
--weights
:训练后的权重文件--source
:验证的图片地址--data
:可选,训练数据集位置--imgsz
:验证的图片尺寸--conf-thres
:置信度阈值,大于此值的才会进行标记
执行detect.py
后会在runs
目录中生成一个detect
文件夹,里面的exp*
就是识别结果。
最终产出
本次实验取得了不错的结果,即使在只有30张图片的小数据集上,模型也能实现较为准确的识别效果,每张图片的识别速度约为15ms。这充分展示了YOLOv5作为目标检测算法的强大能力。
完整的代码和相关支持文件可以在以下链接获取: