竞赛选题 深度学习YOLO抽烟行为检测 - python opencv
文章目录
- 1 前言
- 1 课题背景
- 2 实现效果
- 3 Yolov5算法
- 3.1 简介
- 3.2 相关技术
- 4 数据集处理及实验
- 5 部分核心代码
- 6 最后
1 前言
🔥 优质竞赛项目系列,今天要分享的是
🚩 基于深度学习YOLO抽烟行为检测
该项目较为新颖,适合作为竞赛课题方向,学长非常推荐!
🥇学长这里给一个题目综合评分(每项满分5分)
- 难度系数:3分
- 工作量:3分
- 创新点:4分
🧿 更多资料, 项目分享:
https://gitee.com/dancheng-senior/postgraduate
1 课题背景
公共场合抽烟的危害很大,国家也相应地出台了在公共场合禁烟的政策。以前实行相关的政策都是靠工作人员巡逻发现并出言禁止,这样做效率很低下。计算机视觉领域发展迅速,而抽烟检测也属于一种计算机视觉目标检测的行为,可以采用目标检测的方法来实现。目前,目标检测在很多领域都取得显著成就,但是在抽烟检测领域方面进行研究却几乎没有。该研究可以有效节省成本,对公共场合禁烟政策的实行有很大的推动作用。
2 实现效果
左图为原图,右图为推理后的图片,以图片方式展示,视频流和实时流也能达到这个效果,由于视频转GIF大小原因,这里暂不演示。
3 Yolov5算法
3.1 简介
YOLO系列是基于深度学习的回归方法。该系列陆续诞生出YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5。YOLOv5算法,它是一种单阶段目标检测的算法,该算法可以根据落地要求灵活地通过chaneel和layer的控制因子来配置和调节模型,所以在比赛和落地中应用比较多。同时它有YOLOv5x、YOLOv5l、YOLOv5m、YOLOv5s四种模型。
具有以下优点:
- 在pytorch环境下编写;
- 可以很容易编译成ON⁃NX和Core ML;
- 运行速度很快,每秒可以达到140FPS的速度;
- 模型精度高;
- 集成了YOLOv3和YOLOv4的部分优秀特性,进行了推陈出新的改进。
3.2 相关技术
Mosaic数据增强
Mosaic数据增强技术采用了四张图片的随机缩放、随机剪裁、随机排布的方式对数据进行拼接,相比CutMix数据增强多用了两张图片。在目标识别过程中,要识别的目标有大目标、中等目标、小目标,并且三种目标的占比例不均衡,其中,小目标的数量是最多的,但是出现的频率很低,这种情况就会导致在bp时对小目标的优化不足,模型正确识别小目标的难度比识别中、大目标的难度要大很多,于是对于小目标来说很容易出现误检和漏检的情况。Mosaic数据增强技术做出改进后,上述的问题得到有效的解决。
该技术的优点是:
- 丰富了数据集,采用“三个随机”的方式对数据进行拼接丰富了检测的数据集,尤其是随机缩放增加了很多小目标,克服了小目标的不足,让网络的鲁棒性得到提高;
- 减少GPU的使用,在Mosaic增强训练时,四张图片拼接在一起,GPU可以直接计算四张图片的数据,让Mini-batch的大小减少了很多,这使得一个GPU就可以达到比较可观的效果。
自适应anchor
自适应anchor是check_anchors函数通过遗传算法与Kmeans迭代算出的最大可能召回率的anchor组合。在网络模型的训练过程中,网络在初始化的锚框的基础上输出预测框,然后与真实框groundtruth进行对比,计算两个框之间的差值,再根据差值进行反向更新,迭代网络参数,最后求出最佳的锚框值。自适应的anchor能够更好地配合网络训练,提高模型的精度,减少对anchor的设计难度,具有很好的实用性。
自适应图片缩放
为了提高模型的推理速度,YOLOv5提出自适应图片缩放,根据长宽比对图像进行缩放,并添加最少的黑边,减少计算量。该方法是用缩放后的长边减去短边再对32进行取余运算,求出padding。在训练时并没有采用缩减黑边的方法,该方法只是在测试模型推理的时候才使用,这样提高了目标检测的准确率和速度。
Focus结构
该结构采用切片操作,将特征切片成四份,每一份将当成下采样的特征,然后在channel维度进行concat。例如:原始608 608
3的数据图片,经过切片操作先变成304 304 12的特征图,再经过一次32个卷积核的卷积操作,变成304 304 32的特征图。
CSP结构
YOLOv5中的CSP[5]结构应用于两处,一处是CSP1_X结构应用于Backbone的主干网络中,另一处的CSP2_X结构应用于Neck中,用于加强网络的特征融合的能力。CSPNet主要从网络结构设计的角度解决推理中从计算量很大的问题。该结构的优点有:1)增强CNN的学习能力,使得模型在轻量化的同时保持较高的准确性;2)减低计算的瓶颈问题;3)减低内存的分险。
PFN+PAN结构
这个结构是FPN和PAN的联合。FPN是自顶向下的,将高层的特征信息通过上采样的方式进行传递融合,得到进行预测的特征图,而PAN正好与FPN的方向是相反的方向,它是自底向上地采取特征信息。两个结构各自从不同的主干层对不同的检测层进行参数聚合。两个结构的强强联合让得到的特征图的特征更加明显和清楚。
Bounding box的损失函数
Bounding
box损失函数[6]增加了相交尺度的衡量方式,有效缓解了当两个框不相交和两个框大小完全相同的两种特殊情况。因为当预测框和目标框不相交时,IOU=0,无法反应两个框距离的远近的时候,此时的损失函数不可导;两个框大小完全相同,两个IOU也相同,IOU_LOSS无法区分以上两种特殊情况。
nms非极大值抑制
在目标检测过程的后续处理中,对于大量的目标框的筛选问题,通常会进行nms操作,以此来达到一个不错的效果。YO⁃LOv5算法同样采用了加权的nms操作。
4 数据集处理及实验
数据集准备
由于目前针对吸烟图片并没有现成的数据集,我们使用Python爬虫利用关键字在互联网上获得的图片数据,编写程序爬了1w张,筛选下来有近1000张可用,以及其他途径获取到的,暂时可用数据集有5k张,
深度学习图像标注软件众多,按照不同分类标准有多中类型,本文使用LabelImg单机标注软件进行标注。LabelImg是基于角点的标注方式产生边界框,对图片进行标注得到xml格式的标注文件,由于边界框对检测精度的影响较大因此采用手动标注,并没有使用自动标注软件。
考虑到有的朋友时间不足,博主提供了标注好的数据集和训练好的模型,需要请联系。
数据标注简介
通过pip指令即可安装
pip install labelimg
在命令行中输入labelimg即可打开
5 部分核心代码
# data/smoke.yaml# COCO 2017 dataset http://cocodataset.org# Download command: bash yolov5/data/get_coco2017.sh# Train command: python train.py --data ./data/coco.yaml# Dataset should be placed next to yolov5 folder:# /parent_folder# /coco# /yolov5# train and val datasets (image directory or *.txt file with image paths)train: data\train.txt # 上面我们生成的train,根据自己的路径进行更改val: data\test.txt # 上面我们生成的test#test: ../coco/test-dev2017.txt # 20k images for submission to https://competitions.codalab.org/competitions/20794# number of classesnc: 1 #训练的类别# class namesnames: ['smoke']# Print classes# with open('data/coco.yaml') as f:# d = yaml.load(f, Loader=yaml.FullLoader) # dict# for i, x in enumerate(d['names']):# print(i, x)# model/yolov5s.yaml# parametersnc: 1 # number of classesdepth_multiple: 0.33 # model depth multiplewidth_multiple: 0.50 # layer channel multiple# anchorsanchors:- [116,90, 156,198, 373,326] # P5/32- [30,61, 62,45, 59,119] # P4/16- [10,13, 16,30, 33,23] # P3/8# YOLOv5 backbonebackbone:# [from, number, module, args][[-1, 1, Focus, [64, 3]], # 0-P1/2[-1, 1, Conv, [128, 3, 2]], # 1-P2/4[-1, 3, BottleneckCSP, [128]],[-1, 1, Conv, [256, 3, 2]], # 3-P3/8[-1, 9, BottleneckCSP, [256]],[-1, 1, Conv, [512, 3, 2]], # 5-P4/16[-1, 9, BottleneckCSP, [512]],[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32[-1, 1, SPP, [1024, [5, 9, 13]]],]# YOLOv5 headhead:[[-1, 3, BottleneckCSP, [1024, False]], # 9[-1, 1, Conv, [512, 1, 1]],[-1, 1, nn.Upsample, [None, 2, 'nearest']],[[-1, 6], 1, Concat, [1]], # cat backbone P4[-1, 3, BottleneckCSP, [512, False]], # 13[-1, 1, Conv, [256, 1, 1]],[-1, 1, nn.Upsample, [None, 2, 'nearest']],[[-1, 4], 1, Concat, [1]], # cat backbone P3[-1, 3, BottleneckCSP, [256, False]],[-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]], # 18 (P3/8-small)[-2, 1, Conv, [256, 3, 2]],[[-1, 14], 1, Concat, [1]], # cat head P4[-1, 3, BottleneckCSP, [512, False]],[-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]], # 22 (P4/16-medium)[-2, 1, Conv, [512, 3, 2]],[[-1, 10], 1, Concat, [1]], # cat head P5[-1, 3, BottleneckCSP, [1024, False]],[-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]], # 26 (P5/32-large)[[], 1, Detect, [nc, anchors]], # Detect(P5, P4, P3)]# 训练部分主函数if __name__ == '__main__':check_git_status()parser = argparse.ArgumentParser()parser.add_argument('--epochs', type=int, default=300)parser.add_argument('--batch-size', type=int, default=16)parser.add_argument('--cfg', type=str, default='models/yolov5s.yaml', help='*.cfg path')parser.add_argument('--data', type=str, default='data/smoke.yaml', help='*.data path')parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='train,test sizes')parser.add_argument('--rect', action='store_true', help='rectangular training')parser.add_argument('--resume', action='store_true', help='resume training from last.pt')parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')parser.add_argument('--notest', action='store_true', help='only test final epoch')parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check')parser.add_argument('--evolve', action='store_true', help='evolve hyperparameters')parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')parser.add_argument('--cache-images', action='store_true', help='cache images for faster training')parser.add_argument('--weights', type=str, default='', help='initial weights path')parser.add_argument('--name', default='', help='renames results.txt to results_name.txt if supplied')parser.add_argument('--device', default='0', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')parser.add_argument('--adam', action='store_true', help='use adam optimizer')parser.add_argument('--multi-scale', action='store_true', help='vary img-size +/- 50%')parser.add_argument('--single-cls', action='store_true', help='train as single-class dataset')opt = parser.parse_args()opt.weights = last if opt.resume else opt.weightsopt.cfg = check_file(opt.cfg) # check fileopt.data = check_file(opt.data) # check fileprint(opt)opt.img_size.extend([opt.img_size[-1]] * (2 - len(opt.img_size))) # extend to 2 sizes (train, test)device = torch_utils.select_device(opt.device, apex=mixed_precision, batch_size=opt.batch_size)if device.type == 'cpu':mixed_precision = False# Trainif not opt.evolve:tb_writer = SummaryWriter(comment=opt.name)print('Start Tensorboard with "tensorboard --logdir=runs", view at http://localhost:6006/')train(hyp)# Evolve hyperparameters (optional)else:tb_writer = Noneopt.notest, opt.nosave = True, True # only test/save final epochif opt.bucket:os.system('gsutil cp gs://%s/evolve.txt .' % opt.bucket) # download evolve.txt if existsfor _ in range(10): # generations to evolveif os.path.exists('evolve.txt'): # if evolve.txt exists: select best hyps and mutate# Select parent(s)parent = 'single' # parent selection method: 'single' or 'weighted'x = np.loadtxt('evolve.txt', ndmin=2)n = min(5, len(x)) # number of previous results to considerx = x[np.argsort(-fitness(x))][:n] # top n mutationsw = fitness(x) - fitness(x).min() # weightsif parent == 'single' or len(x) == 1:# x = x[random.randint(0, n - 1)] # random selectionx = x[random.choices(range(n), weights=w)[0]] # weighted selectionelif parent == 'weighted':x = (x * w.reshape(n, 1)).sum(0) / w.sum() # weighted combination# Mutatemp, s = 0.9, 0.2 # mutation probability, sigmanpr = np.randomnpr.seed(int(time.time()))g = np.array([1, 1, 1, 1, 1, 1, 1, 0, .1, 1, 0, 1, 1, 1, 1, 1, 1, 1]) # gainsng = len(g)v = np.ones(ng)while all(v == 1): # mutate until a change occurs (prevent duplicates)v = (g * (npr.random(ng) < mp) * npr.randn(ng) * npr.random() * s + 1).clip(0.3, 3.0)for i, k in enumerate(hyp.keys()): # plt.hist(v.ravel(), 300)hyp[k] = x[i + 7] * v[i] # mutate# Clip to limitskeys = ['lr0', 'iou_t', 'momentum', 'weight_decay', 'hsv_s', 'hsv_v', 'translate', 'scale', 'fl_gamma']limits = [(1e-5, 1e-2), (0.00, 0.70), (0.60, 0.98), (0, 0.001), (0, .9), (0, .9), (0, .9), (0, .9), (0, 3)]for k, v in zip(keys, limits):hyp[k] = np.clip(hyp[k], v[0], v[1])# Train mutationresults = train(hyp.copy())# Write mutation resultsprint_mutation(hyp, results, opt.bucket)# Plot results# plot_evolution_results(hyp)
6 最后
🧿 更多资料, 项目分享:
https://gitee.com/dancheng-senior/postgraduate
相关文章:

竞赛选题 深度学习YOLO抽烟行为检测 - python opencv
文章目录 1 前言1 课题背景2 实现效果3 Yolov5算法3.1 简介3.2 相关技术 4 数据集处理及实验5 部分核心代码6 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于深度学习YOLO抽烟行为检测 该项目较为新颖,适合作为竞赛课…...
mysql利用mysqldump方式搭建主从
背景:线上环境在主库不停服的情况下,利用mysqldump的方式搭建从库。 建议:在主库比较小的情况下(个人建议50G左右),主库不停服可以利用mysqldump搭建从库。如果主库很大,建议利用mysql热备份工…...
如何保护IP在线隐私,提高网络安全?
在数字时代,我们的在线IP隐私面临着越来越多的威胁。黑客、广告商和第三方机构都试图获取我们的个人信息和浏览习惯。因此,保护您的在线IP隐私至关重要。本文将介绍一些简单但有效的方法,帮助您保护自己的隐私。 使用防关联浏览器:…...
掌握 C++ 编译过程:面试中常见问题解析
C是一种高级编程语言,但是计算机并不能直接理解它。因此,需要将C代码翻译成计算机可以理解的机器语言。这个过程就是编译过程,是C程序从源代码到可执行文件的转换过程,包括预处理、编译、汇编和链接四个阶段 预处理 在编译器开始…...
了解Qt QScreen的geometry ,size
目的 了解qt 对于屏幕的size, geometry含义, 更能有效实现最大化, 向下还原逻辑操作 Test 目前我有两个屏 ,1920x1080, 3840*2160. 检测当前程序所在screen(1920x1080)下属性 int screenNum…...

云安全—云计算基础
0x00 前言 学习云安全,那么必然要对云计算相关的内容进行学习和了解,所以云安全会分为两个部分来进行,首先是云计算先关的内容。 0x01 云计算 广泛传播 云计算最早大范围传播是2006年,8月,在圣何塞【1】举办的SES&a…...

【ARM Coresight Debug 系列 16 -- Linux 断点 BRK 中断使用详细介绍】
文章目录 1.1 ARM BRK 指令1.2 BRK 立即数宏定义介绍1.3 断点异常处理流程1.3.1 el1_sync_handler1.3.2 el1_dbg 跟踪 1.4 debug 异常处理函数注册1.4.1 brk 处理函数的注册 1.1 ARM BRK 指令 ARMv8 架构的 BRK 指令是用于生成一个软件断点的。当处理器执行到 BRK 指令时&…...
Rust星号(*)的作用-基础篇
在Rust中,*符号具有多种不同的用途,具体取决于它的使用方式。以下是Rust中*常见的用法. 1.解引用指针 当作为一元运算符放在指针变量之前时,*用于解引用指针并访问它指向的值。在Rust中,通常更推荐使用引用而不是原始指针。引用…...

企业该如何选择数字化转型工具?
对于希望在当今快速发展的商业环境中增强运营、提高效率并保持竞争力的公司来说,选择正确的数字化转型工具是一项关键决策。以下是选择数字化转型工具的关键步骤和注意事项: 1.定义业务目标: 清楚地阐明您的业务目的和目标。了解您希望通过数…...

element ui 中 el-button重新渲染后disabled属性失效
调试发现:disabled绑定的值和显示没有保持一致,发现是disabled属性失效 解决方式: 给标签添加key 比如:key“isOldVersion” <el-form-item><el-button type"primary" style"margin-left: 100px;" click"…...
WebRTC AIMD算法用处
WebRTC使用AIMD(Additive Increase Multiplicative Decrease)算法来进行码率控制。 在WebRTC中,码率控制的目标是优化音视频传输的质量和稳定性,以适应网络状况的变化。具体而言,AIMD算法通过监测网络的拥塞情况&…...
迁移kubelet、docker和containerd工作目录
文章目录 问题背景迁移Docker停止 Docker 服务修改配置移动文件重新启动 Docker 服务 containerd停止服务修改配置移动文件重新启动服务 kubelet(遇到问题待解决)停止服务修改配置移动文件(遇到问题待解决)重新启动服务 使用的版本…...
Go 重构:尽量避免使用 else、break 和 continue
今天,我想谈谈相当简单的事情。我不会发明什么,但我在生产代码中经常看到这样的事情,所以我不能回避这个话题。 我经常要解开多个复杂的 if else 结构。多余的缩进、过多的逻辑只会加深理解。首先,这篇文章的主要目的是让代码更透…...

Unity3D 程序员常用的核心类及方法详解
Unity3D是一款强大的游戏引擎,广泛应用于游戏开发领域。作为Unity3D程序员,掌握常用的核心类及方法是非常重要的。本文将详细介绍Unity3D中程序员常用的核心类及方法,并给出代码实现。 对惹,这里有一个游戏开发交流小组ÿ…...

76.C++ STL list容器
目录 1.什么是list容器 2.list构造函数 3. 元素插⼊和删除操作 4.大小操作 5.赋值操作 6.数据存取操作 7.反转、排序 1.什么是list容器 list 是 C 标准库提供的双向链表容器。它与 vector 和 deque 不同,不是连续的内存块,而是由节点组成的链表结…...

使用FreeMarker导出word文档(支持循环导出实时多张图片)
续上一期的更新内容 ,导出的是单张图片,直接在路径的src 里面填写对应的占位符,就可以了,随着需求的变化,那么今天我们继续往下写一个循环导出多张图片到word里面。 使用FreeMarker导出word文档(支持导出单张图片) …...
Evaluating Open-Domain Question Answering in the Era of Large Language Models
本文是LLM系列文章,针对《Evaluating Open-Domain Question Answering in the Era of Large Language Models》的翻译。 大语言模型时代的开放域问答评价 摘要1 引言2 相关工作3 开放域QA评估4 评估开放域QA模型的策略5 正确答案的语言分析6 CuratedTREC上的正则表…...

基于安卓Android的掌上酒店预订APP
项目介绍 网络的广泛应用给生活带来了十分的便利。所以把掌上酒店预订与现在网络相结合,利用java技术建设掌上酒店预订APP,实现掌上酒店预订的信息化。则对于进一步提高掌上酒店预订发展,丰富掌上酒店预订经验能起到不少的促进作用。 掌上酒…...
搭建CNFS文件系统
1.概念: CNFS (Cluster Network File System)是 GPFS 中的一种模式,用于配置和管理多台服务器(节点)之间的文件共享和数据访问 它允许多个节点同时访问和共享文件系统的数据,以实现高性能、高可…...

网络工程师知识点7
111、IS-IS路由器的三种类型? Level-1路由器(只能创建level-1的LSDB) Level-2路由器(只能创建level-2的LSDB) Level-1-2路由器(路由器默认的类型,能同时创建level-1和level-2的LSDB)…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...

使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
深入解析 ReentrantLock:原理、公平锁与非公平锁的较量
ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...

Qt/C++学习系列之列表使用记录
Qt/C学习系列之列表使用记录 前言列表的初始化界面初始化设置名称获取简单设置 单元格存储总结 前言 列表的使用主要基于QTableWidget控件,同步使用QTableWidgetItem进行单元格的设置,最后可以使用QAxObject进行单元格的数据读出将数据进行存储。接下来…...