当前位置:数码通 > 趋势

用简洁的语言解释YOLO算法

来源于 数码通 2023-10-04 14:36

YOLO算法,英文全称是You Only Look Once,只需谷歌英文全名即可找到论文。与此同时,作者还在github上开源了代码。需要注意的是,这条推文是关于 yolo v1 的,并且还有升级版本。

顾名思义,该算法只需看一次图片就可以识别所有物体。该算法可以实现实时物体检测,可以达到每秒40帧左右,速度非常快。那么如何开始使用这个算法呢?相信大家已经看过很多介绍YOLO算法的文章,所以这里不打算深入讲解这个算法。相反,我会尝试用简洁的语言来解释这个令人着迷的算法。

与其他推文最大的不同在于,我会从实用的角度介绍如何自己创建一个数据集,以及如何让计算机识别特定的物体。

我们先来看看我实现的效果。首先,我随机在办公桌上找到了那个蓝色的水杯,收集了200多张自己水杯的照片。为了减少工作量,我将原车辆(汽车)的数据全部替换为水杯数据集。经过十几个小时的训练,结果如下:

那么如何实现呢?首先,我认为你需要先“理解”这个算法。至少你需要了解它是如何实现的,原理是什么,输入输出是什么。为了学习这个算法,我还花了很多时间阅读作者的论文和代码。我认为论文与代码结合是一种很好的学习方式。通过代码,你可以清楚地了解它是如何实现这个算法的。

该算法的核心在于它将图片划分为7*7的网格。注意,这些7*7的网格并不是将一张图片切割成49个小块,而是一个网格会对应一个输出结果。可能看起来有点抽象,我们先看图。

比如上图中,一共有49个格子。每个网格的任务是确定对象的center点是否落在该网格上。如果落在自己的格子上,那么好吧,那么这个格子就会向系统报告。假设我们把上图中标记的红色格子命名为小格子,然后小格子发现这里好像有一只狗,于是它向系统报告:我这里有一只狗,然后系统询问: 怎么样,狗有多宽多高?小哥显得有些疑惑,不过根据经验,小哥大概能猜到,于是他回答系统:这只狗宽约100像素,高约250像素。至此,小网格的任务就基本完成了。小格子只是49个格子中的一个,其他格子都一样。于是系统收集了49个格子的意见,然后得到了下图。

事实上,这张图中可以出现49*2=81个预测框,这意味着没有一个网格可以对目标有两次预测,所以最多可以出现81个预测框。从图中可以看到,实际上会有很多无用的盒子,相邻的网格可能会有类似的结果。这样我们就可以通过最大值抑制来过滤掉一些预测框。然后就可以得到下面的结果了。

但相信我,即使你已经理解了我上面所说的一切,你也可能无法一下子理解代码。当我阅读代码时,我发现虽然代码不多,逻辑也比较清晰,但是有一些细节还是让人摸不着头脑。难以理解。那么就让我带你经历一下吧!

比较重要的代码主要在pasal_m.smtshopping.cn、m.smtshopping.cn、yolo_m.smtshopping.cn和traim.smtshopping.cn中。加载数据的代码位于pasal_m.smtshopping.cn中。代码并不难,但是需要注意的是,一张图片的标签实际上是一个7*7*25的矩阵。一个25向量由这样组成:第一个是0或1,表示是否有物体,然后接下来的四位是包围盒的信息,即(x, y, w ,h),剩下的就是one-hot编码表类别。预测结果是7*7*30,因为需要预测两个框。

另外一个至关重要的就是它的损失函数的定义,它计算每个预测值的均方误差,但是惩罚的程度不同。

其中,λcoord = 5.0,λnoobj = 1.0,λclasses = 2.0,但是小编不知道这组数字是怎么得到的。它可能是经过大量测试得出的一组最优结果。该解决方案也可以从数学公式导出。其实还有很多难以描述的小细节。如果你想把一个小细节解释清楚,就会涉及到无数的细节,所以我建议你自己通过代码来了解细节。

当你已经理解了代码之后,就很容易实现文章开头的效果了。然后我会解释一下我的想法和过程。最重要的是自己去做。当你研究它的数据集时,你会发现这个数据集的标注是一个xml文件,每张图片都对应一个xml文件。收集完数据集后,就可以对数据集进行标记,但是最简单的xml文件格式需要如下:

这是我的数据集中的注解,也是能够满足代码的最简单的注解。我自己写了一个程序来帮助我完成标注,但是我推荐大家可以使用别人的标注工具,因为毕竟别人已经写好了,没必要重新发明轮子。

这是一个标注工具,不过我没用过,但从描述来看,应该符合要求。完成图像标注后,我们需要考虑如何修改其数据集?一张一张的粘贴起来很难吗?当然可以,但是工作量很大。好吧,让电脑来处理吧。我在加载数据集的时候做了一个判断。如果这张图中有一辆车,我就不会加载数据,并指定一个路径让它加载我们准备好的数据集。

findcar = 0for objs 中的 obj: cls_ind = obj.find('name').text.lower().strip() if cls_ind == 'car':找车=1次

接下来你要思考如何解决它。当你解决了这个问题并且可以训练的时候,如果不出意外的话,你应该能够得到和我一样的结果。祝你好运!

-->
登录后参与评论