理论部分
上图展示的应用场景,比如人体技术、工业上的缺陷检测、医学图像的病灶检测、智能座舱以及自动驾驶等都离不开目标检测。
因此,目标检测在计算机视觉中属于非常基础性的技术。
1. 基础知识
提到目标检测,不得不提到图像分类。
图像分类也是非常基础的工作,它是以一张图片作为输入,输出图片包含的物体类别以及分数。分数指有多大的置信度认为它是某一个类别。
目标检测任务相对于图像任务更进了一步,它会针对一个或者多个目标的图片,检测出其中目标的位置,分辨其类别并给出分数。
目标检测要训练模型首先要进行数据标注,标注出矩形框以及类别。矩形框一般使用左上+右下两个坐标的形式表示,即(x1,y1,x2,y2,class,score),class是类别,score是分数。有了标注之后,才能进行模型的训练。
目标检测模型的输入为一张图像,经过检测模型后,输出若干个物体的检测结果,结果主要包括:
- 检测框,形式为(x1,y1,x2,y2)
- 类别
- 分数
PASCAL VOC是目标检测常用的数据集,见证了目标检测从传统方法到深度学习方法发展的历程。该数据集包含20个常见类别,除了比较知名的目标检测以外,还提供了其他任务的标注。
MS COCO也是常用数据集,它见证了目标检测百花齐放的阶段,到目前为止仍然有很多主流方法在该数据集上进行测评。该数据集拥有30万+图片与250万+实例标注,提供了80个类别的目标。
上图下方是COCO与PASCAL VOC的对比,无论是类别的数量还是实例的数量,COCO都更胜一筹。
目标检测的重要操作包括:
① IoU(Intersection over Union):表示两个矩形框的重叠程度。计算公式如右上方所示,其分子是绿色矩形框与红色矩形框的交集,分母是两个矩形框的并集。重叠度越高,IoU越接近于1。
② NMS(Non-Maximum Suppression):非极大值抑制,目的为去掉多个重复的预测框。模检测模型预测一张图时的初次结果往往不理想,一个目标可能会预测出多个框,因此需要使用非极大值抑制去除冗余的框,最终得到上图左边图像。
NMS的具体流程可以概括为:设定一个IoU阈值,将每一个类别的预测框按照分数做降序排序,再根据矩形框的IoU进行抑制。如果比某个框分数更高的框的IoU大于阈值,则此框将被抑制。
比如右边图片中有两个人,共预测了5个框,上面三个框是骑马的人。假设三个框的分数是0.91、0.80与0.79,最高分0.91。如果分数较低的两个框的IoU超过阈值,则该两个框会被抑制。
上图列出了精度与速度上较常见的目标检测评价指标。
其中精度方面有:
- 准确率(Precision):检测出正确的框的数量/检测出所有框的数量。以骑马图为例,假设红色的框是标注框,蓝色与橙色框是预测出的两个框,分数分别为0.9和0.6。正确的框指与标注框的IoU相差超过一定的阈值,且其类别相同。因此,蓝色框符合正确的标准,它是正确的框,但橙色不是正确的框。因此,该示例准确率是1/2。
- 召回率(Recall):检测出的正确框的数量/标注的所有框数量。本示例中,标注的所有框是红色的框,数量为1。检测出的正确框是蓝色的框,因此召回率为1/1=1。
- lPR曲线:如上图右下角所示,其纵轴是准确率precision,横轴是recall,因此这条线被称为PR曲线。它由多个点构成,每个点是precision/recall值。此处将引入置信度分数阈值概念。以骑马图为例,假设将置信度分数的阈值设为0,则橙色框与蓝色框都是预测结果;但如果将分数阈值设为0.7,橙色框将被过滤。对于不同的分数阈值,预测结果会一直变化,因此算出的precision/recall也是变化的。
- AP(Average Precision):指PR曲线与坐标轴围成的面积。因为precision与recall都在0到1之间,因此AP最大为1。
- mAP:AP为针对单个类别,而mAP为多个类别时所有类别的平均AP,为检测中的常用指标。
2.代表性方法
上图为COCO上目标检测的部分方法。
对目标检测的方法做归类,如上图所示。
基础的网络分为CNN(卷积神经网络)与Transformer。CNN又可以分为二阶段目标检测与一阶段目标检测。
二阶段目标检测指在目标网络里存在一个候选框生成的阶段,被称为第一阶段;第二阶段进行候选框的微调与以及最终结果的预测。其中最具代表性的工作是Faster RCNN,针对此前非端到端的方法实现了端到端。基于该方法也产生了一系列二阶段的经典方法。
一阶段的方法从一开始的SSD到后来的YOLO也产生了一系列方法。
而Transformer最初在NLP领域应用较为广泛,将Transformer应用到目标检测主要是DETR。在DETR工作出现之后,也有了一系列对DETR的改进工作。
Fastern RCNN、YOLO以及DETR是三个分支里程碑式的工作。
传统的目标检测方法思路较为直接,采用滑动窗口,对原图像逐个设置一定的步长进行滑动,对每区域进行分类和定位。
以右图为例,蓝色的窗框是滑窗,可以沿着图像从左往右、从上到下进行滑动,每到一个区域都会判断该区域是背景或是前景的物体,并判断是否需要对其进行微调。
但传统方法存在一些问题:
- 效率较低,滑动的方式导致会对特征进行重复提取,计算资源或效率都非常低下。
- 精度较低,对尺寸以及光照的变化不鲁棒。
那么,二阶段Faster RCNN做了哪些改进?
Faster RCNN的流程为:一张图片进来之后,会有CNN网络负责对图片做特征提取,得到一张特征图像,由RPN生成候选框并提取;第二阶段检测头再根据生成的候选框进行位置的微调以及类别的判断,得到位置、类别以及分数的信息。
该方式的优势在于:
- 是首个端到端的方式,依靠CNN的训练进行优化。
- 特征提取的效率较高,使用CNN统一提取特征,因此不存在重复提取的情况
- 精度相对较高,使用两阶段提取proposal再到微调的方式,对尺寸与小物体相对较鲁棒。
不足在于:速度未达到30FPS实时的要求。为了解决速度问题,业界诞生了一阶段目标检测。
YOLO的思路为:取消了提取候选框的步骤,而是直接使用完整的CNN网络对图片特征进行一次提取,同时会将图片划分为s*s的网格,每个网格负责预测周边的框,进行目标的分类和回归,最后经过NMS等后处理得到最终的结果。
该方式的优势在于:
- 速度更快,不需要两阶段生成候选框。
- 网络更简洁,通用性也更高。
因此,YOLO系列一经推出即大受关注,前段时间已经推出V8版本。
其不足在于,单阶段导致精度有所下降,特别是对于较小的物体。
目标检测领域的新范式DETR引入了Transform结构,也使用了CNN做特征提取,区别在于会将图片进行一定的切分,将其组织为token的形式。CNN提取出的特征里面每一个像素是一个token。token作为encoder与decoder的输入,进行特征提取。
DETR的另一特点是引入了object query,基于query预测最终的目标。采用集合预测的思路,去除了NMS、候选框等以往检测的常用操作。
该方式作为目标检测新范式,优势为无需复杂的自定义操作,实现上更加简单和优雅。但不足为训练时间比较长,同时对小物体的检测精度较差。
3. 展望总结
前文主要了解了图像检测的基本知识,包括任务定义、数据集、评价指标等;也了解了图像检测的代表性方法,包括二阶段的Faster-RCNN、一阶段的YOLO以及基于Transformer的DETR。
本文介绍的目标检测只是非常小的一部分,未来我们期望从更细化的方向,比如长尾的问题、零样本、少样本、增量问题以及更通用的方向,比如最近提出的SAM、Grounded-SAM等进行普及。
实战演示
1. ModelScope图像检测模型介绍
上图为ModelScope主页截图,可以从最上方的检测专题进入,也可以从左边的计算机视觉、视觉检测跟踪tag进入。比如点击垂类目标检测,将会显示人体口罩、香烟等垂偏垂直行业的检测模型。
ModelScope上的泛检测类的模型可以归类为图片、视频及其他。
图像检测包括通用的目标检测、人脸相关检测。通用检测提供了实时的目标检测,也有DINO高精度目标检测以及自研的DAMOYOLO模型。垂类目标检测包括口罩、安全帽、无人机等垂直行业的模型。
视频检测提供了视频目标检测、视频目标跟踪、单目标/多目标以及视频动作检测等模型,也有更细化的方向比如3D目标检测、Open World目标检测、长尾/少样本目标检测、显著性、伪装目标检测等。本文实战主要基于实时目标检测、实时安全帽检测两个模型。
2. 创空间实战(安全帽检测)
本示例将演示如何基于ModelScope的安全帽检测模型,搭建创空间的应用。主要包括4个步骤,分别是创建创空间、准备需要的文件(启动脚本、说明文档)、上传文件,发布创空间。关于创空间的搭建,文档中心提供了非常详细的介绍。
在ModelScope页面右上角点击创建创空间。
填写相关信息,英文名创建后不可更改,license可以根据需要进行修改。填入空间描述,接入SDK目前支持3种,选择默认的Gradio即可。
需要用到的文件包括app.py的启动脚本、一张示例图片以及readme文件。
app.py会进行模块的导入,导入Gradio模块,Gradio是Python包,可以用于搭建机器学习模型的web应用。声明安全帽的检测器,该检测器基于ModelScope上已有的安全帽检测模型构建。
下面是可视化的函数,输入图片和检测结果,最后返回可视化之后的图片。safaty_helmet_detect函数是主要的函数,串起了整个流程,图片作为输入,用检测器检测得到结果,对图片以及检测结果做可视化,得到输出图片并返回。
最后,用Gradio构建interface。title、description与examples都可以进行设置。构建好interface之后,通过launch()函数启动。
readme文档的前半部分是YAML,后半部分是Markdown,内容可以根据自己的需要填写。YAML主要进行格式的控制,可以设置domain、models、license以及入参、启动脚本等。
创空间创建完毕后,页面会显示基础介绍。
为了方便展示,本次实战直接使用网页端进行操作。此处默认已经有readme的文件,复制提前编写好的readme的内容粘贴至默认readme文件中,添加app.py文件,上传示例图片。
回到ModelScope,添加app.py文件。
此时创空间位未发布状态,需要在设置里点击上线创空间。
发布后的页面如上图所示。
上传图片后即可进行安全帽检测,输出结果如右图。
3. 检测模型实战(安全帽检测)
模型的实战或者实操,经常会提到推理、评估以及训练三个词。
推理是指:有了模型后,对一张图片做前向的推理,得到输出结果,再通过结果判断模型的效果如何,主要为定性分析。
评估是指:模型在已有数据集上的精度水平如何,主要为定量分析。
训练是指:如果已有模型的精度无法达到要求或检测的类别不符合要求,需要做精度提升或类别扩充,对模型进行训练和微调。
模型的实操一般可以分为下面三类:
第一类:无代码。比如OpenVI自学习平台,在网页上完成图片的标注到模型训练再到最终的部署,用鼠标即可完成,全程无代码。
第二类:低代码。比如ModelScope,对底层代码做了封装,向上以模块的形式透出,只需少量的代码便可以进行模型的训练等。
第三类:高代码。比如mmdetection等,代码的开发量较大。
上图中从左到右代码能力要求逐渐递增,而模型的丰富程度也会逐渐递增,灵活性更大。
本示例主要演示如何将COCO上的通用检测模型(不包含安全帽检测模型)通过训练得到安全帽检测模型。
本示例主要基于实时目标检测通用领域的检测模型,大家可以通过名字或modelID进行搜索得到模型的model卡,下方展示了模型的详细介绍、适用范围以、推理示例代码、训练微调的示例代码。
点击右上角Notebook快速开发,选择GPU环境。
先进行目录上的准备,操作与本地基本相似。创建新的目录tutorial(名字可以根据需要任意取),在该目录下创建Notebook的脚本,命名为tutorial(名字可以根据需要任意取,建议用英文命名)。
主要代码如上图所示。首先要做模块的引入,除了内置的模块,基本都为ModelScope的模块。Notebook已经预置了ModelScope等包,如果在本地,则需要安装ModelScope。
复制模块引入的代码,运行代码,完成模块的导入。复制数据集下载相关代码,运行代码,完成数据集加载。
在ModelScope页面的数据集tab,搜索数据集的名称即可找到对应的数据集。
关于如何创建新的数据集,可以在文档中心找到详细的参考。
接下来还需要进行训练的超参设置以及开启模型训练。
modelID是modelcard上的模型ID,work_dir是本次训练的工作目录。batchsize为8代表一次可以训练8张图片,该参数会影响训练的速度,数值大小需要根据GPU的显存决定。total_epochs是总的迭代轮次,本次示例为基于通用检测到安全帽检测的微调,因此total_epoch设为15足够。
参数设置完成之后,构建cfg_options字典,键值为xx.xx的嵌套方式,比如tarin.max_epochs。
模型文件里,每一个模型都有一个configuration.json的文件,是默认的配置文件。构建字典主要作用为对默认的JSON文件进行修改。
开启训练的代码包含构建字典的入参,包括modelID、构建好的train与eval的数据集、工作目录等。然后用build_trainer创建trainer,下载预训练模型,最后调用trainer.train开启训练。
训练完成后,work_dir工作目录下会生成上图文件,包括日志文件、pth模型以及模型的输出。output文件可以用于模型的推理,内容如上图中下方图片所示。
复制训练相关代码并执行。
首先会进行模型的下载,显示默认的配置文件。
训练结束后显示mAP为0.61,IoU为0.5的时候mAP为0.91,基本符合预期。
如果训练完后需要对模型做进一步评估,可以使用trainer的eval接口。
复制相关代码,运行,即可对验证集单独做一次评估,结果显示mAP的数值与上面一致。
如果要利用已经训好的模型再对图片进行推理,需要使用推理以及可视化部分代码。
复制推理相关代码,注意,此处需要进行修改。model处需要使用output的目录做路径的拼接。input图片可以是URL,也可以使用本地图片的路径。上传一张准备好的安全帽图片,设置其路径。运行,即可输出检测结果。
如果想要实现可视化,则复制可视化相关代码,对代码中的图片名称进行修改,运行代码,即可显示上图结果。
至此,我们完成了利用安全帽的数据,从通用检测模型训练得到安全帽检测模型,并用模型进行评估和推理。