目标检测误检与负样本问题

在线体验各类最新模型,更有模型 免费Token 额度领取!
立即体验
简介: 目标检测误检与负样本问题

在做目标检测算法模型的时候,有时候会遇到模型预测,效果不好,或者误识别的情况(明明人眼都能识别出来的东西, 模型却识别错误,像狗识别成猫都好理解,但会遇到一个衣服会识别成猫的),出现这些误检问题分几种情况:


1.图像内容问题

2.目标bbox范围问题

解决这样的问题,可以试着使用语义分割来规避掉,但相对成本太大了


增加负样本是最为简单的一种方法,下面也将详细介绍使用负样本相关的问题。


目标检测负样本问题


误检

图像内容问题

数据增强,会改变目标的一定特征,使其特征发生变化,识别错误


在训练人脸检测网络时,一般都会做数据增强,为图像模拟不同姿态、不同光照等复杂情况,这就有可能产生过亮的人脸图像,“过亮”的人脸看起来就像发光的灯泡一样。。。如果 发光灯泡 经过网络提取得到的特征,和 过亮人脸 经过网络提取得到的特征相似度达到临界值,那么网络把发光灯泡检测为人脸就不足为奇了。


同样的道理,用于训练网络的人脸数据集中,若是存在一些带口罩,带围巾的人脸图像,那么网络就极有可能“记住”口罩、围巾的特征,在预测阶段,要是有物体(比如衣服)表现得像口罩、围巾,那么网络就有可能把该物体检测成人脸。


目标 bbox 的范围问题


标注的目标框,内容有除想要检测的特征以外的特征事物,使其让模型混淆,学习到错误的特征


目前非常流行的深度学习目标检测网络(SSD、YOLO、RetinaFace 等)在训练阶段,我们需要提供目标在图像中的 bbox,所谓 bbox,其实主要就是指目标的外接矩形。这样训练而来的网络在预测阶段,一般给出的也是目标的外接矩形。


问题就出在 bbox 上,接下来的讨论还是以人脸检测为例,请看下图:

cbb8fdc0cf8e41f4be9ea000a9efe032.png


这是一个典型的目标 bbox。bbox 本质上是矩形,但通常目标(人脸)不是矩形,bbox 内部包含一些非人脸内容, 我认为这些非人脸内容要对误检负一部分责任 。


常用的人脸检测网络一般使用大量的卷积层提取图像特征,得到的特征图尺寸通常小于原始输入图像数倍(取决于卷积的 stride、padding 等参数),网络对特征图的每一个“像素点”做二分类(人脸类、背景类),“误检”就是在这个二分类过程中产生的。


负样本

定义


负样本是指不包含任务所要识别的目标的图像,也叫负图像(Negtive Image)。以识别限速牌为例,如下所示,左图包含限速牌,为正样本,右图不包含限速牌,为背景图,即负样本增加负样本


为什么使用负样本


训练负样本的目的是为了降低误检测率、误识别率,提高网络模型的泛化能力。通俗地讲就是告诉检测器,这些“不是你要检测的目标”。


如何收集负样本


可以通过下面两种方式收集负样本:


采用本任务场景的不包含目标物体的背景图像,例如你的目标是识别某园区内的行人,那么所有本园区内不包含行人的图片都视作负样本。不要使用不属于本任务场景的负图像,因为其对检测器的性能影响不大。

测试图像中被识别错误的目标所在区域。(通常对原图像进行裁剪,使得裁剪下来的图像只包含误识别的物体,而不包含目标)


如何训练负样本


将正负样本集及其标签作为训练集送入模型训练即可。

注意:正负样本必须放在一起训练,不能单独训练负样本,否则经过训练,网络会把所有的图像都识别为背景。正负样本的比例最好为1:1到1:2左右,数量差距不能太悬殊,特别是正样本数量本来就不太多的情况下。

制作负样本代码,因为我们的Annotations中缺失了一部分没有标注的文件


import os
import xml.dom.minidom
img_path = 'Downloads/DatasetId_1656670_1665712200/Images/'
xml_path = 'Downloads/DatasetId_1656670_1665712200/Annotations/'
xmls = os.listdir(xml_path)
for img_file in os.listdir(img_path):
    if img_file.split('.')[0] not in xmls:
        img_name = os.path.splitext(img_file)[0]
        #create an empty dom document object
        doc = xml.dom.minidom.Document()
        #creat a root node which name is annotation
        annotation = doc.createElement('annotation')
        #add the root node to the dom document object
        doc.appendChild(annotation)
        #add the folder subnode
        folder = doc.createElement('folder')
        folder_text = doc.createTextNode('VOC2012')
        folder.appendChild(folder_text)
        annotation.appendChild(folder)
        #add the filename subnode
        filename = doc.createElement('filename')
        filename_text = doc.createTextNode(img_file)
        filename.appendChild(filename_text)
        annotation.appendChild(filename)
        # add the path subnode
        path = doc.createElement('path')
        path_text = doc.createTextNode(img_path + img_file)
        path.appendChild(path_text)
        annotation.appendChild(path)
        #add the source subnode
        source = doc.createElement('source')
        database = doc.createElement('database')
        database_text = doc.createTextNode('Unknown')
        source.appendChild(database)
        database.appendChild(database_text)
        annotation.appendChild(source)
        #add the size subnode
        size = doc.createElement('size')
        width = doc.createElement('width')
        width_text = doc.createTextNode('1920')
        height = doc.createElement('height')
        height_text = doc.createTextNode('1080')
        depth = doc.createElement('depth')
        depth_text = doc.createTextNode('3')
        size.appendChild(width)
        width.appendChild(width_text)
        size.appendChild(height)
        height.appendChild(height_text)
        size.appendChild(depth)
        depth.appendChild(depth_text)
        annotation.appendChild(size)
        #add the segmented subnode
        segmented = doc.createElement('segmented')
        segmented_text = doc.createTextNode('0')
        segmented.appendChild(segmented_text)
        annotation.appendChild(segmented)
        #write into the xml text file
        open(xml_path+'%s.xml'%img_name,'w').close()
        fp = open(xml_path+'%s.xml'%img_name, 'w+')
        doc.writexml(fp, indent='\t', addindent='\t', newl='\n', encoding='utf-8')
        fp.close()
相关文章
|
监控 数据可视化 API
yolo-nas无人机高空红外热数据小目标检测(教程+代码)
yolo-nas无人机高空红外热数据小目标检测(教程+代码)
|
监控 PyTorch 算法框架/工具
Qwen-VL怎么用自己的数据集微调
Qwen-VL怎么用自己的数据集微调
2109 0
|
5月前
|
机器学习/深度学习 监控 算法
基于 YOLO26的5类人体行为姿态智能检测(中英文双版) | 附完整源码与效果演示
本文介绍了基于YOLO26的人体行为姿态智能检测系统的设计与实现。该系统采用YOLO26作为基础模型,实现了对5种人体行为姿态的实时检测。系统的主要特点包括: 高精度:采用YOLO26作为基础模型,结合数据增强和模型优化技术,提高了检测精度。 实时性:YOLO26的推理速度快,能够实现实时人体行为姿态检测。 多场景适应性:模型在不同场景下都能保持较好的检测性能。 易于部署:系统的安装和部署过程简单,便于在实际应用中使用。 基于YOLO26的人体行为姿态智能检测系统在智能安防、体育训练、智能家居等领域具有广泛的应用前景。未来,我们将进一步优化模型,提高检测精度和速度,拓展检测的行为类别,为更多
|
7月前
|
人工智能 计算机视觉 测试技术
Meta SAM3开源
Meta发布并开源SAM 3,首个支持文本、点、框等多提示的统一图像视频分割模型,突破性实现开放词汇概念的全实例分割。基于Meta Perception Encoder与DETR架构,结合AI与人工协同数据引擎,构建超400万概念数据集,在SA-Co基准达人类水平75%-80%。支持大规模可提示分割与跟踪,推动视觉基础模型新进展。(239字)
|
PyTorch 算法框架/工具
Jetson学习笔记(四):pth(torch模型文件)转trt(tensorrt引擎文件)实操
关于如何使用torch2trt工具将PyTorch模型转换为TensorRT引擎文件的实操指南。
946 1
Jetson学习笔记(四):pth(torch模型文件)转trt(tensorrt引擎文件)实操
|
机器学习/深度学习 编解码 监控
目标检测实战(六): 使用YOLOv8完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
这篇文章详细介绍了如何使用YOLOv8进行目标检测任务,包括环境搭建、数据准备、模型训练、验证测试以及模型转换等完整流程。
28520 59
目标检测实战(六): 使用YOLOv8完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
XML 机器学习/深度学习 数据格式
YOLOv8训练自己的数据集+常用传参说明
YOLOv8训练自己的数据集+常用传参说明
27269 3
|
计算机视觉 Python
目标检测笔记(四):自适应缩放技术Letterbox完整代码和结果展示
自适应缩放技术Letterbox通过计算缩放比例并填充灰边像素,将图片调整为所需尺寸,保持原始比例不变,广泛应用于目标检测领域。
1204 1
目标检测笔记(四):自适应缩放技术Letterbox完整代码和结果展示
|
机器学习/深度学习 存储 缓存
YOLOv5的Tricks | 【Trick9】模型剪枝处理与Pytorch实现的剪枝策略
在yolov5项目中的torch_utils.py文件下,有prune这个函数,用来实现模型的剪枝处理。对模型裁剪,模型剪枝这方面之前没有接触到,这里用这篇笔记来学习记录一下这方面内容。
3094 0
YOLOv5的Tricks | 【Trick9】模型剪枝处理与Pytorch实现的剪枝策略
|
机器学习/深度学习 算法 Go
YOLOv5网络结构解析
YOLOv5网络结构解析
10411 1

热门文章

最新文章