【yolov1】详解yolov1理论 代码

news2024/11/17 1:57:08

目标检测要解决的3大问题:

1、有没有?

图片中是否有要检测的物体?(检测物体,判定前景背景)

2、是什么?

这些物体分别是什么?(检测到的物体是什么)

3、在哪里?

这些物体在哪里?(画框,描边,变色都行)

yolov1模型图

在这里插入图片描述

一.预测阶段

1.2 预测阶段后处理

在这里插入图片描述
把7x7x2=98个预测框进行筛选过滤,重复的预测框只保留一个。最终得到预测结果。
包括:

1.过滤掉置信度低的框
2.非极大值抑制

在这里插入图片描述
选出一个grid cell,它有30个值。每个grid cell预测两个预测框,用10个值表示。后面20个值是条件概率,即在该grid中存在目标的情况下,是某一个类的概率。

在这里插入图片描述

  用置信度与后面20个类的条件概率相乘得到每一个类的概率。
将全概率p() 拆分成 p(该 grid cell 存在目标的概率) x p(| 该grid cell 存在目标的概率)。
这样本来需要40个维度才能表示的概率,变成两个置信度和一个20维的条件概率即可。

在这里插入图片描述

将置信度 x 条件概率后,每个框生成两个20维的向量,表示每一个类的概率。
一共生成 7x7x2 = 9820维度的向量。

在这里插入图片描述

7x7x30的信息,可视化获得了中间图的结果。

1.2 后处理

在这里插入图片描述

把7x7x30的张量,变成目标检测结果。

在这里插入图片描述

假如第一行是dog类
1.设置dog类的概率如果<0.2,则置为0.
2.将dog类按照值进行排序。概率高的放在前面。
3.对排序之后的结果进行NMS。

1.3 NMS

取置信度值最大的框,bb47,它的框是黄色的部分。
在这里插入图片描述

先把第一个框跟第二框比较。如果他们的IOU>一个阈值,那么认为他们两个重复识别了一个目标。(可能一个图像上有多只猫,7x7个gred cell 每个都对猫预测了两个框,共有98个预测框,这98个预测框,可能有好些个预测的不是图像上的同一个猫)
就把低置信度的框过滤掉。 (即将它设置为0

在这里插入图片描述

用bb47与其它框做IOU计算,过滤掉一些框之后,从第二个值非0的框,开始让它与其它非0的框再做一个IOU计算。

对每个类重复上面的结果。

最后得到一个稀疏的矩阵。
把不为0的索引找出来,表示类别。把分数值也取出来,可视化。

在这里插入图片描述

二.训练阶段

训练阶段没有NMS,
如下:训练阶段有个Ground True ,是人工标注的真实框。

我们的算法是为了拟合这个框,让损失函数最小化。
真实的框在哪个grid cell,就让这个grid cell预测的一个bodding box去拟合这个框。
两个预测框具体让哪一个框预测要看这两个预测框与真实框的IOU。
另一个框和其它Grid cell 预测的框只需要让他们置信度越来越小即可。

在这里插入图片描述

在这里插入图片描述

https://www.bilibili.com/video/BV15w411Z7LG?p=5&vd_source=ebc47f36e62b223817b8e0edff181613

每个预测框对应 维度为2x5 + 20 = 30的向量。 
20代表:yolov1用的数据有20个类别。这20个类别用独热编码表示,是哪个类别就让该类别标记为1.
5代表 : 4个坐标和一个置信度。
置信度计算的是预测边框 与 真实边框的 IOU,IOU用来选择哪个边框作为预测边框。

损失函数的设计:
要让与预测框 与 真实框的Loss变的很小。

负责预测物体的框,要与真实框Ground truth从坐标和宽高上都尽量一致。

在这里插入图片描述

1.计算预测中心点与真实中心点的损失。
2.计算预测的宽高与真实宽高的损失。

用根号,是使得小框对误差更敏感。

第三项负责计算置信度的误差

标签值是预测框真实框的IOU,作为标签值。

第四项是不负责检测目标的框,让它们的Loss值越小越好。让他们的权重小一些,因为他们比较多。

第五项:负责检测物体那个框的分类误差。比如真实框类别标注是狗,那么预测的类别是狗的概率让它越来越接近1。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

预测结果

在这里插入图片描述

当物体中心落到某个网格中,该网格就负责预测这个物体。
每个网络会生成两个预测框,所以yolov1共有 7x7x2=98个预测框,相对于fast-rcnn成百上千个预测框,yolov1少了很多。

参考:https://zhuanlan.zhihu.com/p/595221376

损失函数

在这里插入图片描述

1.对坐标进行预测,坐标损失

预测第i个网格,的第j个bbox是否有该object。 方法是计算每个网格的两个bbox与真实框的IOU,IOU最大bbox对应的网格中包含这个object。

在这里插入图片描述
在这里插入图片描述
如果不用根号,则是个线性关系 w越大,该物体与小物体的loss就越大。模型的学习会收到它的影响,主要去满足大物体去了。

超参数 λ_coord 默认是5,是为了平衡非物体(背景)的bbox过多的影响。因为目标对于背景来说是很小的,损失函数占比的权重就很小。

置信度损失

在这里插入图片描述
此时加入了一个非物体的置信度和权重 λnoobj=0.5,如果 让一个网络去学习n个类别的分类,那么必须让网络学习n+1个类别的分类。1是背景。背景占比比较多,所以调小它的权重。

对类别进行预测

判断是否有object的中心落入网格中,网格中包含有object的中心,就负责预测该object的类别概率。
在这里插入图片描述
直接预测类别-真实类别,这个方法不好,后面Yolo对它改进。

在这里插入图片描述
拥挤物体的中心,会跑到一个网格中去,那么一个网络就会预测两个物体。很不好。
对小物体检测也不好,小物体权重小。
对不规则物体(长宽比不正常)

voc数据集

以PASCAL VOC2017为例,它包含如下5个文件夹:

Annotations
JPEGImages
ImageSets
SegmentationClass
SegmentationObject

JPEGImages

PASCAL VOC提供的所有的图片,其中包括训练图片,测试图片。

Annotations

xml格式的标签文件,每个xml对应JPEGImage中的一张图片。各个目标的位置和类别。以(x,y)的格式不保存坐标点。
<annotation>  
    <folder>VOC2012</folder>                             
    <filename>2007_000392.jpg</filename> //文件名  
    <source>                             //图像来源(不重要)  
        <database>The VOC2007 Database</database>  
        <annotation>PASCAL VOC2007</annotation>  
        <image>flickr</image>  
    </source>  
    <size>                              //图像尺寸(长宽以及通道数)                        
        <width>500</width>  
        <height>332</height>  
        <depth>3</depth>  
    </size>  
    <segmented>1</segmented>            //是否用于分割(在图像物体识别中01无所谓)  
    <object>                            //检测到的物体  
        <name>horse</name>              //物体类别  
        <pose>Right</pose>              //拍摄角度  
        <truncated>0</truncated>        //是否被截断(0表示完整)  
        <difficult>0</difficult>        //目标是否难以识别(0表示容易识别)  
        <bndbox>                        //bounding-box(包含左下角和右上角xy坐标)  
            <xmin>100</xmin>  
            <ymin>96</ymin>  
            <xmax>355</xmax>  
            <ymax>324</ymax>  
        </bndbox>  
    </object>  
    <object>              //检测到多个物体  
        <name>person</name>  
        <pose>Unspecified</pose>  
        <truncated>0</truncated>  
        <difficult>0</difficult>  
        <bndbox>  
            <xmin>198</xmin>  
            <ymin>58</ymin>  
            <xmax>286</xmax>  
            <ymax>197</ymax>  
        </bndbox>  
    </object>  
</annotation> 

ImageSets

训练要用到的:

1.train.txt:训练集 (注意,均为图片名,没有后缀。以train.txt为例,分为两列,第一列为图像名如00012;第二列为-11-1表示目标在对应的图像没有出现,1则表示出现。)
2.val.txt:验证集
3.trainval.txt:训练和验证集
# 训练用不到的其它内容
Action:人的动作
Layout:人体的具体部位
Main: 图像物体识别的数据,总共20, 需要保证train val没有交集。
Segmentation:用于分割的数据
验证集(val)与测试集(test)是有区别的。
验证集:val是validation的简称,验证是否过拟合、以及用来调节训练参数等。
测试集:当模型训练完成后,用于检测模型的准确性。

https://blog.csdn.net/weixin_43570470/article/details/123659793

write_txt.py

'''
    读取XML文件信息
'''

import xml.etree.ElementTree as ET
import os
import random

VOC_CLASSES = (  # 定义所有的类名
    'aeroplane', 'bicycle', 'bird', 'boat',
    'bottle', 'bus', 'car', 'cat', 'chair',
    'cow', 'diningtable', 'dog', 'horse',
    'motorbike', 'person', 'pottedplant',
    'sheep', 'sofa', 'train', 'tvmonitor')   # 使用其他训练集需要更改
# 创建两个文件用于存放
train_set = open('voctrain.txt', 'w')
test_set = open('voctest.txt', 'w')
Annotations = 'VOCdevkit/VOC2017/Annotations'
# 返回Annotations文件下的所有文件名 (里面是所有xml文件,一个图片对应一个xml文件,是对图片的标注)
xml_files = os.listdir(Annotations)
# 打乱数据集
random.shuffle(xml_files)

train_num = int(len(xml_files) * 0.7) # 设置训练集个数
train_lists= xml_files[:train_num] # 训练集列表
test_lists= xml_files[train_num:] # 测试集列表

def parse_rec(filename): # 输入xml文件名
    tree = ET.parse(filename)
    objects = []
    # 读取xml文件中的 <object></object>下的内容
    '''
    <object>                            //检测到的物体  
        <name>horse</name>              //物体类别  
        <pose>Right</pose>              //拍摄角度  
        <truncated>0</truncated>        //是否被截断(0表示完整)  
        <difficult>0</difficult>        //目标是否难以识别(0表示容易识别)  
        <bndbox>                        //bounding-box(包含左下角和右上角xy坐标)  
            <xmin>100</xmin>  
            <ymin>96</ymin>  
            <xmax>355</xmax>  
            <ymax>324</ymax>  
        </bndbox>  
    </object>  

    '''
    for obj in tree.findall('object'):
        # 创建一个结构体
        obj_struct = {}
        # 获取到 difficult元素,如果值为1,表示目标难以识别,则跳过
        difficult = int(obj.findall('difficult').text)
        if difficult ==1:
            continue
        obj_struct['name'] = obj.find('name').text
        bbox = obj.find('bndbox')
        obj_struct['bbox'] = [int(float(bbox.find('xmin').text)),
                             int(float(bbox.find('ymin').text)),
                             int(float(bbox.find('xmax').text)),
                             int(float(bbox.find('ymax').text))]
        objects.append(obj_struct)

    return objects

def write_txt():
    count = 0
    for train_list in train_lists: # 生成训练集txt
        count += 1
        image_name = train_list.split('.')[0] + '.jpg'  # 图片文件名
        results = parse_rec(Annotations + train_list)
        if len(results) == 0:
            print(train_list)
            continue
        train_set.write(image_name)
        for result in results:
            class_name = result['name']
            bbox = result['bbox']
            class_name = VOC_CLASSES.index(class_name)
            train_set.write(' ' + str(bbox[0]) +
                            ' ' + str(bbox[1]) +
                            ' ' + str(bbox[2]) +
                            ' ' + str(bbox[3]) +
                            ' ' + str(class_name))
        train_set.write('\n')
    train_set.close()

    for test_list in test_lists:   # 生成测试集txt
        count += 1
        image_name = test_list.split('.')[0] + '.jpg'  # 图片文件名
        results = parse_rec(Annotations + test_list)
        if len(results) == 0:
            print(test_list)
            continue
        test_set.write(image_name)
        for result in results:
            class_name = result['name']
            bbox = result['bbox']
            class_name = VOC_CLASSES.index(class_name)
            test_set.write(' ' + str(bbox[0]) +
                            ' ' + str(bbox[1]) +
                            ' ' + str(bbox[2]) +
                            ' ' + str(bbox[3]) +
                            ' ' + str(class_name))
        test_set.write('\n')
    test_set.close()


if __name__ == '__main__':
    write_txt()

最终生成的训练集和数据集标签如下:
红框中前四个数是左上和右下角坐标,第五个数是类别。
一个图片可能否有多个目标,所有可能会有多个红框。
在这里插入图片描述

yoloData.py

encoder结果是7x7x30 = 7x7x(20+5+5)
20是这个数据集有20类,两个5是因为让这7x7个格子,每个格式产生两个候选框。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1047551.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

做外贸你的差不多可能差的很多

人们常说不想当将军的士兵不是好士兵&#xff0c;然而当不好士兵的将军一定不是一个好将军&#xff0c;我们对事情或者自我的要求衡量越低的时候&#xff0c;当以什么事情都差不多为标准的时候&#xff0c;可能我们自己也就只能最高混到差不多而已了。 就拿简单的书写来说&…

高频工业RFID读写器的主要应用

随着通信技术的迅速发展&#xff0c;RFID的应用也逐渐广泛&#xff0c;产线、零售、身份识别、金融领域、门禁安全等各个方面都有RFID的身影。其中很多应用都是以高频技术应用为主&#xff0c;下面我们就跟大家一起来了解一下&#xff0c;高频工业RFID读写器的主要应用包括哪些…

高可靠性振弦采集仪可减少对仪器维护保养

高可靠性振弦采集仪可减少对仪器维护保养 振弦采集仪是一种用于测量机械设备振动和振动频率的仪器。在现代工业中&#xff0c;振动是许多机械故障的先兆&#xff0c;因此振动监测是维护和预测设备发生故障的重要手段。高可靠性振弦采集仪可以大大减少机械设备的维护保养成本&am…

查询表中的全部列的数据

MySQL从小白到总裁完整教程目录:https://blog.csdn.net/weixin_67859959/article/details/129334507?spm1001.2014.3001.5502 语法格式: select from * 表名; 说明: * 表示所有列 由于不写where子句&#xff0c;表示无条件&#xff0c;找到所有的行&#xff01; 准备工作:执…

阿里云 Oss 权限控制

前言 最近公司的私有 Oss 服务满了&#xff0c;且 Oss 地址需要设置权限&#xff0c;只有当前系统的登录用户才能访问 Oss 下载地址。一开始想着用 Nginx 做个转发来着&#xff0c;Nginx 每当检测当前请求包含特定的 Oss 地址就转发到我们的统一鉴权接口上去&#xff0c;但是紧…

拿到 Offer 了!深信服 17K*15

作者 | 磊哥 来源 | 公众号&#xff1a;Java中文社群 转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09; 这两年的就业情况大家是有目共睹的&#xff0c;作为一个双非院校的学生&#xff0c;能拿到深信服 Java 研发岗的工作&#xff0c;学生本人还是很满意的&…

【操作工具】IDEA创建类及已有类添加注释-详细操作

1.背景 很多开发好多时候其实不太会给类添加注释&#xff0c;尤其是已经有的类&#xff0c;上网查询&#xff0c;好多文档错误百出&#xff0c;而且不全 2.正文 2.1新建类添加注释 idea给新建类创建注释有两种方式 先写一个简单的模板 /** * description: TODO * autho…

从小白到精通,十九项案例实践丨全流程HEC-RAS 1D/2D水动力与水环境模拟

水动力与水环境模型的数值模拟是实现水资源规划、环境影响分析、防洪规划以及未来气候变化下预测和分析的主要手段。然而&#xff0c;一方面水动力和水环境模型的使用非常复杂&#xff0c;理论繁复&#xff1b;另一方面&#xff0c;免费的水动力和水环境软件往往缺少重要功能&a…

怎么查看win10分辨率?我来告诉你!

Windows 10 是一个强大的操作系统&#xff0c;可以适应各种屏幕和硬件配置。然而&#xff0c;在某些情况下&#xff0c;您可能需要查看或更改显示器的分辨率设置&#xff0c;以获得最佳的图像和屏幕显示效果。本文将介绍怎么查看win10分辨率的2种方法&#xff0c;以帮助您快速查…

MySQL 全球大会summit 2023年度 --- MySQL 高可用和灾备 (音译)

开头还是介绍一下群&#xff0c;如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, Oceanbase, Sql Server等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友…

聚观早报 | 中国队拿下亚运会电竞项目首金;B站发布68部国创片单

【聚观365】9月28日消息 中国队拿下亚运会电竞项目首金 B站发布68部国创片单 支付宝持续加大流量开放 起点有声书《宿命之环》等大作陆续上线 方程豹豹5详细配置公开 中国队拿下亚运会电竞项目首金 杭州2022年第19届亚运会官网发布公告称&#xff0c;在昨日的杭州第19届亚…

2014 款金旅牌小型客车 发动机怠速抖动、加速无力

故障现象 一辆2014款金旅牌小型客车&#xff0c;搭载JM491Q-ME发动机&#xff0c;累计行驶里程约为20万km。车主反映&#xff0c;最近该车发动机怠速抖动、加速无力&#xff0c;且经常缺少冷却液。 故障诊断 根据车主描述的故障现象&#xff0c;初步判断该车气缸垫损坏&#…

分类预测 | MATLAB实现SSA-FS-SVM麻雀算法同步优化特征选择结合支持向量机分类预测

分类预测 | MATLAB实现SSA-FS-SVM麻雀算法同步优化特征选择结合支持向量机分类预测 目录 分类预测 | MATLAB实现SSA-FS-SVM麻雀算法同步优化特征选择结合支持向量机分类预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 MATLAB实现SSA-FS-SVM麻雀算法同步优化特征选择结…

【iOS逆向与安全】插件开发之某音App直播间自动发666

1.目标 由于看直播的时候主播叫我发 666&#xff0c;支持他&#xff0c;我肯定支持他呀&#xff0c;就一直发&#xff0c;可是后来发现太浪费时间了&#xff0c;能不能做一个直播间自动发 666 呢&#xff1f;于是就花了几分钟做了一个。 2.操作环境 越狱iPhone一台 frida ma…

Java【手撕链表】LeetCode 2. “两数相加“, 图文详解思路分析 + 代码

文章目录 前言一、两数相加1, 题目2, 思路分析3, 代码 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: &#x1f4d5; JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等 &#x1f4d7; Java数据结构: 顺序表, 链表, 堆…

五、过拟合问题与正则化

一、过拟合问题 &#xff08;一&#xff09;问题的提出 过拟合问题的定义&#xff0c;以线性回归为例&#xff0c;在房价预测的数据集中&#xff0c;假设函数产生的曲线有三种情况&#xff0c;如下图&#xff1a; &#xff08;1&#xff09;欠拟合&#xff08;2&#xff09;…

保姆级 -- Zookeeper超详解

1. Zookeeper 是什么(了解) Zookeeper 是一个 分布式协调服务 的开源框架, 主要用来解决分布式集群中应用系统的一致性问题, 例如怎样避免同时操作同一数据造成脏读的问题. ZooKeeper 本质上是 一个分布式的小文件存储系统 . 提供基于类似于文件系统的目录树方式的数据存储, …

【Linux】线程同步和互斥

目录 一、线程互斥1.相关概念2.互斥锁&#xff08;mutex&#xff09;3.互斥锁的原理4.自定义封装一个锁 二、可重入和线程安全三、死锁死锁概念死锁四个必要条件如何避免死锁 四、线程同步1.条件变量概念条件变量接口基于阻塞队列实现生产者消费者模型 2.信号量概念信号量操作接…

Databend 源码阅读:配置管理

作者&#xff1a;尚卓燃&#xff08;PsiACE&#xff09;澳门科技大学在读硕士&#xff0c;Databend 研发工程师实习生 Apache OpenDAL(Incubating) Committer https://github.com/PsiACE 对于 Databend 这样复杂的数据库服务端程序&#xff0c;往往需要支持大量的可配置选项&am…

探索Lighthouse性能分数计算背后的奥秘

本文作者为 360 奇舞团前端开发工程师 作为开发我们都知道&#xff0c;页面性能很重要&#xff0c;一个性能良好的页面可以给用户带来非常好的用户体验。那么&#xff0c;怎么能知道自己写的页面性能是好是坏呢&#xff1f; Lighthouse 是Chrome提供给开发者用来测量页面性能的…