python生成文字点选验证码→训练yolo目标检测模型→识别文字点选验证码

目录

  • python生成文字点选验证码→训练yolo目标检测模型→识别文字点选验证码
    • 前言
      • 一、生成文字点选验证码
      • 二、YOLOv3
      • 三、YOLOv5
      • 四、识别效果
      • 五、参考链接
  • 写在最后

前言

  • 就在去年的这个时候,我写了python生成验证码→处理验证码→建立CNN模型训练→测试模型准确率→识别验证码这篇文章,开启了我的CNN学习之旅
  • 接着过了半年,我又写了python+DCGAN模型生成验证码+训练CNN模型+测试模型准确率这篇文章,又开启了我的GAN学习之旅
  • 那么,接下来,即将开启我的YOLO学习之旅

一、生成文字点选验证码

作为十几年杰迷的我,那必须得弄点范特西的数据集,于是乎,我想到了,用周杰伦的歌曲名称+专辑封面来生成我的文字点选验证码图片,效果如下:

原图 添加随机歌名之后

具体实现逻辑如下:

  1. 从专辑图片中随机选取一张作为背景,并将其大小改为520x520
  2. 从歌曲中随机选取1~5首歌曲的歌名
  3. 遍历选取到的几首歌曲的歌名
  4. 从40~50的字号中随机选取一个字号
  5. 从-90°~90°中随机选取文字旋转的角度
  6. 从所有颜色中随机选取一种字体颜色
  7. 以及在背景图片中随机选取一个坐标点xmin,ymin
  8. 最后将处理后的文字图片放到背景图片中,以及生成每首歌的归一化后label坐标x,y,w,h

代码如下:

from tqdm import tqdm
from PIL import Image, ImageDraw, ImageFont, ImageOps
import shutil,os
import numpy as npclass CreateData:def __init__(self,create_num):self.jay_img_paths=['JAY/' + i for i in os.listdir('JAY/')] # 背景图片路径self.font_path='../simhei.ttf' # 字体路径self.img_save_path='images/' # 生成训练集图片的路径self.label_save_path='labels/' # 生成图片对应label的路径self.test_path='test/' # 生成测试集图片的路径# 100首周杰伦歌曲名称self.songs=['可爱女人', '星晴', '黑色幽默', '龙卷风', '屋顶', '爱在西元前', '简单爱', '开不了口', '上海一九四三', '双截棍', '安静', '蜗牛', '你比从前快乐', '世界末日', '半岛铁盒', '暗号', '分裂', '爷爷泡的茶','回到过去', '最后的战役', '晴天', '三年二班', '东风破', '你听得到', '她的睫毛', '轨迹', '断了的弦', '七里香', '借口', '搁浅', '园游会', '夜曲', '发如雪', '黑色毛衣', '枫', '浪漫手机', '麦芽糖', '珊瑚海', '一路向北', '听妈妈的话', '千里之外', '退后', '心雨', '白色风车', '千山万水', '不能说的秘密', '牛仔很忙', '彩虹', '青花瓷', '阳光宅男','蒲公英的约定', '我不配', '甜甜的', '最长的电影', '周大侠', '给我一首歌的时间', '花海', '魔术先生', '说好的幸福呢', '時光機','乔克叔叔', '稻香', '说了再见', '好久不见', '愛的飛行日記', '超人不会飞', 'Mine Mine', '公主病', '你好吗', '疗伤烧肉粽', '水手怕水', '世界未末日', '超跑女神', '明明就', '爱你没差', '夢想啟動', '大笨钟', '傻笑', '手语', '乌克丽丽', '哪裡都是你','算什么男人', '怎么了', '我要夏天', '手写的从前', '听爸爸的话','美人魚', '听见下雨的声音', '说走就走', '一点点', '前世情人', '不该', '告白气球', '愛情廢柴', '等你下课', '不爱我就拉倒', '说好不哭', '我是如此相信', 'Mojito', '瓦解']self.song2label={song:i for i,song in enumerate(self.songs)}self.label2song={i:song for i,song in enumerate(self.songs)}self.create_num=create_numself.image_w=520self.image_h=520self.max_iou=0.5  # 每首歌名的boxes的iou不能超过0.5def create_folder(self):while True:try:for path in [self.img_save_path,self.label_save_path,self.test_path]:shutil.rmtree(path,ignore_errors=True)os.makedirs(path,exist_ok=True)breakexcept:passdef bbox_iou(self,box2):'''两两计算iou'''for box1 in self.tmp_boxes:inter_x1=max([box1[0],box2[0]])inter_y1=max([box1[1],box2[1]])inter_x2=min([box1[2],box2[2]])inter_y2=min([box1[3],box2[3]])inter_area=(inter_x2-inter_x1+1) * (inter_y2-inter_y1+1)box1_area=(box1[2]-box1[0]+1) * (box1[3]-box1[1]+1)box2_area=(box2[2]-box2[0]+1) * (box2[3]-box2[1]+1)iou=inter_area / (box1_area + box2_area - inter_area + 1e-16)if iou > self.max_iou:# 只要有一个与之的iou大于阈值则重新来过return iouelse:return 0def draw_text(self,image,image_draw,song):iou=np.infnum=0while iou > self.max_iou:if num >= 100:# 为了避免陷进死循环,如果循环100次都没有找到合适的位置,则iou>0.5的阈值失效breakrandom_font_size=np.random.randint(40,50) # 随机字号random_rotate=np.random.randint(-90,90) # 随机旋转角度random_color=np.random.randint(0,256,3) # 随机字体颜色random_x,random_y=np.random.randint(1,520,2) # 随机xmin,yminfont = ImageFont.truetype(self.font_path, random_font_size)label=self.song2label[song]size_wh=font.getsize(song)img = Image.new('L', size_wh)img_draw = ImageDraw.Draw(img)img_draw.text((0, 0), song, font=font, fill=255)img_rotate = img.rotate(random_rotate, resample=2, expand=True)img_color = ImageOps.colorize(img_rotate, (0,0,0), random_color)w,h=img_color.sizexmin=random_xymin=random_y# 为了避免超出520x520,修正xmin,yminif random_x+w > self.image_w:xmin=self.image_w - w - 2if random_y+h > self.image_h:ymin=self.image_h - h - 2xmax=xmin+wymax=ymin+hboxes=(xmin,ymin,xmax,ymax)iou=self.bbox_iou(boxes)num+=1image.paste(img_color, box=(xmin,ymin), mask=img_rotate)
#         image_draw.rectangle(boxes,outline=tuple(random_color))return image,boxes,labeldef process(self,boxes):'''将xmin,ymin,xmax,ymax转为x,y,w,h以及归一化坐标,生成label'''x1,y1,x2,y2=boxesx=((x1+x2)/2)/self.image_wy=((y1+y2)/2)/self.image_hw=(x2-x1)/self.image_wh=(y2-y1)/self.image_hreturn [x,y,w,h]def main(self):'''主函数'''self.create_folder() # 重置所需文件夹for i in tqdm(range(self.create_num+3)):random_song_num=np.random.randint(1,5) # 随机1~4首random_jay_img_path=np.random.choice(self.jay_img_paths) # 随机背景image=Image.open(random_jay_img_path).convert('RGB').resize((self.image_w,self.image_h))image_draw=ImageDraw.Draw(image)boxes_list=[]label_list=[]self.tmp_boxes=[] # 用于计算两两boxes的ioufor j in range(random_song_num):song=np.random.choice(self.songs)image,boxes,label=self.draw_text(image,image_draw,song)self.tmp_boxes.append(boxes)boxes_list.append(self.process(boxes))label_list.append(label)# save image and labelimage_filename=self.img_save_path+f'image{i}.png' if i < self.create_num else self.test_path+f'test{i}.png'label_filename=self.label_save_path+f'image{i}.txt' if i < self.create_num else self.test_path+f'test{i}.txt'image.save(image_filename)with open(label_filename,'w') as f:for k in range(len(label_list)):# label x y w hf.write(f'{label_list[k]} {boxes_list[k][0]} {boxes_list[k][1]} {boxes_list[k][2]} {boxes_list[k][3]}\n')if __name__ == '__main__':creator=CreateData(5000)creator.main()

二、YOLOv3

代码过多,就不放上来了,直接看结果。

参考了崔庆才崔大写的滑块验证码识别https://github.com/Python3WebSpider/DeepLearningImageCaptcha2,只是修改了dataset相关代码,配置文件信息,以及训练的代码等等。

  • dataset的修改:因为我复现崔大的代码时,发现其label文件的格式是:class xmin ymin w h
    所以就自己重新改写了一下,修改成:class x y w h
  • 配置文件即yolov3.cfg的修改
  1. 三个yolo层的classes参数改为数据集的类别个数,即100
  2. 三个yolo层的上一个convolutional层的filters参数改为3*(类别个数+5),即315
  • 训练策略
  1. epoch:100
  2. batch size:16
  3. img size:416
  4. 数据集划分:80%即4000张用于训练,20%即1000张用于验证
  5. gradient accumulations:5(即被5整除的批次,优化器暂停更新梯度信息)
  6. 优化器:Adam
  • GPU内存占用:15G
  • 训练耗时:4.5小时

训练结果的如下:

Train Loss Valid Loss Valid Metrics

---- best_mAP@0.5: 0.29220820871021674
---- best_epoch: 98

小结

知识巩固:

  • TP: 将正类预测为正类的数量
  • FN: 将正类预测为负类的数量
  • FP: 将负类预测为正类的数量
  • TN: 将负类预测为负类的数量
Accuracy Precision Recall F1 Score
acc=TP+TNTP+TN+FP+FNacc =\frac{TP+TN}{TP+TN+FP+FN} acc=TP+TN+FP+FNTP+TN​ P=TPTP+FPP=\frac{TP}{TP+FP} P=TP+FPTP​ R=TPTP+FNR=\frac{TP}{TP+FN} R=TP+FNTP​ F1=2×P×RP+RF_{1} =2\times \frac{P\times R}{P + R} F1​=2×P+RP×R​
  1. 从验证集的指标看,recall高,precision低,说明FN比FP小。也就是说,模型将一首歌名识别成多首,且多数情况下其中就有一首是预测正确的
  2. 训练了100个epoch,然而mAP@0.5的分数也才0.3左右,提升缓慢
  3. 看趋势,随着训练epoch的增加,各项指标还是会再提升的

三、YOLOv5

代码过多,就不放上来了,直接看结果。

参考了作者的代码https://github.com/ultralytics/yolov5,去掉了我认为是冗余的代码,主要是简化了train.py、val.py和detect.py的代码。

因为yolov5有提供多个模型:yolov5n、yolov5s、yolov5l、yolov5m、yolov5x,于是我就都尝试了一遍。

均采用以下训练策略:

  • epoch:100
  • learning rate:0.001
  • batch size:16
  • image size:416
  • augment:False
  • rect:False
  • quad:False
  • multi scale:True
  • 数据集划分:80%即4000张用于训练,20%即1000张用于验证
  • 优化器:Adam
  • lr scheduler:LambdaLR
  • 配置文件:hyp.scratch.yaml
  • 混合精度训练
  • 不使用平滑标签
  • 评价指标:fitness = 0.1 * mAP@0.5 + 0.9 * mAP@0.5:0.95

1. yolov5n

GPU内存占用:2G
训练耗时:2.2小时
模型大小:7.39MB
---- best_fitness=0.6837750339549021
---- best_epoch=87

训练结果的如下:

Train Loss Valid Loss Valid Metrics

2. yolov5s

GPU内存占用:4.25G
训练耗时:2.5小时
模型大小:27.9MB
---- best_fitness=0.878297457833696
---- best_epoch=99

训练结果的如下:

Train Loss Valid Loss Valid Metrics

3. yolov5l

GPU内存占用:12.8G
训练耗时:3.75小时
模型大小:178MB
---- best_fitness=0.9015696258245549
---- best_epoch=93

训练结果的如下:

Train Loss Valid Loss Valid Metrics

4. yolov5m

GPU内存占用:8.5G
训练耗时:3小时
模型大小:81.4MB
---- best_fitness=0.9197881788592055
---- best_epoch=98

训练结果的如下:

Train Loss Valid Loss Valid Metrics

5. yolov5x

GPU内存占用:15.5G
训练耗时:6.3小时
模型大小:332MB
---- best_fitness=0.9216454715562004
---- best_epoch=100

训练结果的如下:

Train Loss Valid Loss Valid Metrics

小结

  1. yolov5n模型最小,GPU内存占用最小,且训练时长也最短,可惜性能是最差的,但也比yolov3要好,这一点毋容置疑
  2. 如果要考虑GPU内存、模型大小、训练时长和性能,那么yolov5s是最好的选择,性价比最高
  3. yolov5l、yolov5m和yolov5x的性能均达到了90%以上,综合考虑的话,我会选择yolov5m。

四、识别效果

最后,yolov3和yolov5分别对开头的那张图片进行识别,来看看实际的效果吧。(过滤条件均设置为0.5)

因为边幅有限,就比较一张吧,可以看得出来:

  1. yolov3只识别出了等你下课稻香,且置信度也不是很高
  2. yolov5n将稻香识别成傻笑了,以及说好不哭的置信度也不是很高
  3. 剩下的均成功识别出来了四首歌,且置信度都是非常高的。差别可能也不是很明显,可以多用几张图片进行测试,在我测试多几张后,yolov5x是最好的,毕竟分数最高。
yolov3 yolov5n yolov5s
yolov5l yolov5m yolov5x

五、参考链接

周杰伦官方专辑封面高清

崔庆才崔大写的滑块验证码识别

yolov5作者代码


以上即为本篇全部内容,代码我整理了一遍,且运行后无bug,若需要源代码的可以关注我的微信公众号《Python王者之路》,回复关键词:20211226,即可获取。


写在最后

在看了崔大写的滑块验证码识别的推文后,我当时就已经想好了要出这一篇文章了

我先是复现了崔大的代码,当然,这其中遇到了很多的坑,毕竟第一次接触目标检测,之前只是会一点图片分类

可谓说历经千辛万苦,终于成功复现了,当时就想着要不直接写一篇:我的复现过程遇到的问题的文章算了

可是呢,看看yolov3的识别效果,如此难以接受

于是,又开始研究最新的yolov5,因为此时对yolo有了初步的认识,这时复现yolov5还算比较轻松

然后,花了一周左右的时间,测试出了最好的训练策略即本篇采用的策略

最后,又花了一周的时间,按我的训练策略来训练yolov5的5个模型,以及写这篇文章

虽然成功运用yolo模型来做目标检测了,但对于yolo具体细节还有待研究呀~

最后,提前祝大家2022年元旦快乐吧!!

python生成文字点选验证码→训练yolo目标检测模型→识别文字点选验证码相关推荐

  1. 【毕业设计】单片机机器视觉人体识别小车 - 深度学习 yolo目标检测 人体识别 树莓派

    文章目录 0 前言 1 简介 2 主要器件 3 线路连接 4 Yolo环境搭建 5 yolo模型训练 6 模型转化 7 树莓派环境配置 8 最后 0 前言

  2. 目标检测实战:4种YOLO目标检测的C++和Python两种版本实现

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨nihate 审稿丨邓富城 编辑丨极市平台 导读 本文作者使用C++编写一套基于OpenCV的Y ...

  3. 【深度学习】目标检测实战:4种YOLO目标检测的C++和Python两种版本实现

    作者丨nihate 审稿丨邓富城 编辑丨极市平台 导读 本文作者使用C++编写一套基于OpenCV的YOLO目标检测,包含了经典的YOLOv3,YOLOv4,Yolo-Fastest和YOLObile ...

  4. 目标检测实战必会!4种基于YOLO目标检测(Python和C++两种版本实现)

    目标检测实战必会!4种基于YOLO目标检测(Python和C++两种版本实现) AI算法修炼营 1周前 以下文章来源于极市平台 ,作者CV开发者都爱看的 极市平台 专注计算机视觉前沿资讯和技术干货,官 ...

  5. 如何一个模型走天下?集成训练多数据集,打造通用目标检测模型方法详解

    在目标检测的实际应用中,常常会出现需要泛化的目标检测系统的情况.如城市安防中,需要目标检测系统能够检测足够多类别的目标,才能达到更好的安防效果. 但目前常用的目标检测数据集中包含的类别数量有限,使用单 ...

  6. python模型预测_python:目标检测模型预测准确度计算方式(基于IoU)

    训练完目标检测模型之后,需要评价其性能,在不同的阈值下的准确度是多少,有没有漏检,在这里基于IoU(Intersection over Union)来计算. 希望能提供一些思路,如果觉得有用欢迎赞我表 ...

  7. python实现目标识别眼镜_用Python快速实现YOLO目标检测

    文章也同步更新到微信公众号:R语言和Python学堂想获取本文完整代码和数据的下载链接,可关注微信公众号"R语言和Python学堂",并回复发文日期"20181223&q ...

  8. YOLOV3目标检测模型训练实例

    YOLOV3目标检测 从零开始学习使用keras-yolov3进行图片的目标检测,比较详细地记录了准备以及训练过程,提供一个信号灯的目标检测模型训练实例,并提供相关代码与训练集. DEMO测试 YOL ...

  9. 基于YOLO目标检测及OpenCV实现的游戏代玩人工智能体(Auto Gaming Agent) [3] (更新)

    大型生存类游戏自动代玩人工智能[3] -- 目标识别(新) 一.目标检测算法更新 二.YOLOv5模型训练 1. 数据准备 2. 训练模型 三.Pytorch推理预测YOLOv5 1. 引入库 2. ...

  10. 目标检测模型从训练到部署!

    Datawhale干货 作者:张强,Datawhale成员 训练目标检测模型并部署到你的嵌入式设备,让边缘设备长"眼睛". 目标检测的任务是找出图像中所有感兴趣的目标(物体),确定 ...

最新文章

  1. 怎样才可以过大学英语六级啊,有没有好点的方法?【转载】
  2. rancher安装mysql_四、rancher搭建Mysql集群化部署,做到同步备份
  3. Ogre貌似开始推荐MYGUI了~~
  4. javascript之DOM编程正则表达式引入
  5. XCTF_Web_新手练习区:view_source
  6. 让一个文字在背景图片水平居中的方法
  7. java动态语言_探秘Java 7:JVM动态语言支持详解
  8. Effective C++学习笔记(Part One:Item 1-4)
  9. jQueryEasyUI框架 - panel 选项卡高度自适应
  10. 基于centos6.5搭建solr服务器
  11. 对于SQL注入的理解
  12. php 单位食堂订餐,单位饭堂订餐系统(手机订餐)
  13. 自带公网IP上阿里云 | 凌云时刻
  14. Clickhouse分片集群性能测试
  15. shell脚本学习指南-学习(2)
  16. tasklist 结束进程_netstat -ano,ntsd;tasklist,tskill-查看杀死进程命令 | 学步园
  17. DragonFlow导读(by quqi99)
  18. 锂电池电池管理系统 中颖SH367309保护板方案
  19. 计算机资源管理菜单包括哪些,资源管理器文件菜单有哪些命令,资源管理器命令...
  20. 2021年全球与中国木材采伐设备行业市场规模及发展前景分析

热门文章

  1. HTML超链接标签—链接QQ在线聊天
  2. Java web网页版仿QQ实现在线聊天功能系统
  3. NBA2K18手游显示无法连接服务器,nba2k18手游交易被拒绝 | 手游网游页游攻略大全...
  4. $.ligerDialog弹出对话框
  5. 使用git时输错密码解决办法
  6. JavaScript设计模式(2)—— 多种继承方式的实现及原理
  7. 山东理工ACM 1112 C语言实验——图形输出(字符常量练习)
  8. Android C++ Parcel
  9. 发送RST报文的几种可能的情况
  10. 利用rfcomm实现树莓派与手机通信_树莓派可以这样玩