动手学CV-目标检测入门教程:基本概念

3.1 目标检测基本概念

本文来自开源组织 DataWhale 🐳 CV小组创作的目标检测入门教程。
对应开源项目 《动手学CV-Pytorch》 的第3章的内容,教程中涉及的代码也可以在项目中找到,后续会持续更新更多的优质内容,欢迎⭐️。
如果使用我们教程的内容或图片,请在文章醒目位置注明我们的github主页链接:https://github.com/datawhalechina/dive-into-cv-pytorch

3.1.1 什么是目标检测

目标检测是计算机视觉中的一个重要任务,近年来传统目标检测方法已经难以满足人们对目标检测效果的要求,随着深度学习在计算机视觉任务上取得的巨大进展,目前基于深度学习的目标检测算法已经成为主流。

相比较于基于深度学习的图像分类任务,目标检测任务更具难度。

具体区别如图3-1所示。

图像分类:只需要判断输入的图像中是否包含感兴趣物体。

目标检测:需要在识别出图片中目标类别的基础上,还要精确定位到目标的具体位置,并用外接矩形框标出。

在这里插入图片描述

图3-1 分类和目标检测任务示意图

3.1.2 目标检测的思路

自2012年Alex Krizhevsky凭借Alex在ImageNet图像分类挑战赛中拿下冠军之后,深度学习在图像识别尤其是图像分类领域开始大放异彩,大众的视野也重新回到深度神经网络中。紧接着,不断有更深更复杂的网络出现,一再刷新ImageNet图像分类比赛的记录。

大家发现,通过合理的构造,神经网络可以用来预测各种各样的实际问题。于是人们开始了基于CNN的目标检测研究, 但是随着进一步的探索大家发现,似乎CNN并不善于直接预测坐标信息。并且一幅图像中可能出现的物体个数也是不定的,模型如何构建也比较棘手。

因此,人们就想,如果知道了图中某个位置存在物体,再将对应的局部区域送入到分类网络中去进行判别,那我不就可以知道图像中每个物体的位置和类别了吗?

但是,怎么样才能知道每个物体的位置呢?显然我们是没办法知道的,但是我们可以去猜啊!所谓猜,其实就是通过滑窗的方式,罗列图中各种可能的区域,一个个去试,分别送入到分类网络进行分类得到其类别,同时我们会对当前的边界框进行微调,这样对于图像中每个区域都能得到(class,x1,y1,x2,y2)五个属性,汇总后最终就得到了图中物体的类别和坐标信息。

总结一下我们的这种方案思路:先确立众多候选框,再对候选框进行分类和微调。

观察下图2-1,更形象的理解下这种思想:

在这里插入图片描述

图3-2 从分类角度去看目标检测

图3-2展示了一个通过遍历各个区域,然后逐个分类去完成目标检测任务的过程示例。在待识别图上预设一个框,然后逐像素遍历,就能得到大量候选框(这里仅为示意图,图上只展示了3个框用于说明问题,具体数量由图像大小和预设框大小决定),每个框送入到分类网络分类都有一个得分(代表当前框中有一个船的置信度),那么得分最高的就代表识别的最准确的框,其位置就是最终要检测的目标的位置。

以上就是最初的基于深度学习的目标检测问题解决思路,RCNN,YOLO,SSD等众多经典网络模型都是沿着这个思路优化发展的。

本文会基于以上思路,带领大家从0开始一步步搭建一个目标检测模型,并完成模型的训练测试及评价!

3.1.3 目标框定义方式

任何图像任务的训练数据都要包括两项,图片和真实标签信息,通常叫做GT。

图像分类中,标签信息是类别。目标检测的标签信息除了类别label以外,需要同时包含目标的位置信息,也就是目标的外接矩形框bounding box。

用来表达bbox的格式通常有两种,(x1, y1, x2, y2) 和 (c_x, c_y, w, h) ,如图3-3所示:

在这里插入图片描述

图3-3 目标框定义方式

之所以使用两种不同的目标框信息表达格式,是因为两种格式会分别在后续不同场景下更加便于计算。

两种格式互相转换的实现在utils.py中,代码也非常简单:

def xy_to_cxcy(xy):"""Convert bounding boxes from boundary coordinates (x_min, y_min, x_max, y_max) to center-size coordinates (c_x, c_y, w, h).:param xy: bounding boxes in boundary coordinates, a tensor of size (n_boxes, 4):return: bounding boxes in center-size coordinates, a tensor of size (n_boxes, 4)"""return torch.cat([(xy[:, 2:] + xy[:, :2]) / 2,  # c_x, c_yxy[:, 2:] - xy[:, :2]], 1)  # w, hdef cxcy_to_xy(cxcy):"""Convert bounding boxes from center-size coordinates (c_x, c_y, w, h) to boundary coordinates (x_min, y_min, x_max, y_max).:param cxcy: bounding boxes in center-size coordinates, a tensor of size (n_boxes, 4):return: bounding boxes in boundary coordinates, a tensor of size (n_boxes, 4)"""return torch.cat([cxcy[:, :2] - (cxcy[:, 2:] / 2),  # x_min, y_mincxcy[:, :2] + (cxcy[:, 2:] / 2)], 1)  # x_max, y_max

3.1.4 交并比(IoU)

在目标检测任务中,关于IOU的计算贯穿整个模型的训练测试和评价过程,是非常非常重要的一个概念,其目的是用来衡量两个目标框的重叠程度。

IoU的全称是交并比(Intersection over Union),表示两个目标框的交集占其并集的比例。图3-4为IOU计算示意图:

在这里插入图片描述

图3-4 IOU计算示意图

图中可以看到,分子中黄色区域为红bbox和绿bbox的交集,分母中黄+红+绿区域为红bbox和绿bbox的并集,两者之比即为iou。

那么具体怎么去计算呢?这里给出计算流程的简述:

1.首先获取两个框的坐标,红框坐标: 左上(red_x1, red_y1), 右下(red_x2, red_y2),绿框坐标: 左上(green_x1, green_y1),右下(green_x2, green_y2)
2.计算两个框左上点的坐标最大值:(max(red_x1, green_x1), max(red_y1, green_y1)), 和右下点坐标最小值:(min(red_x2, green_x2), min(red_y2, green_y2))
3.利用2算出的信息计算黄框面积:yellow_area
4.计算红绿框的面积:red_area 和 green_area
5.iou = yellow_area / (red_area + green_area - yellow_area)

如果文字表述的不够清晰,就再看下代码:

def find_intersection(set_1, set_2):""" Find the intersection of every box combination between two sets of boxes that are in boundary coordinates.:param set_1: set 1, a tensor of dimensions (n1, 4)                                                                                                           :param set_2: set 2, a tensor of dimensions (n2, 4):return: intersection of each of the boxes in set 1 with respect to each of the boxes in set 2, a tensor of dimensions (n1, n2)"""# PyTorch auto-broadcasts singleton dimensionslower_bounds = torch.max(set_1[:, :2].unsqueeze(1), set_2[:, :2].unsqueeze(0))  # (n1, n2, 2)upper_bounds = torch.min(set_1[:, 2:].unsqueeze(1), set_2[:, 2:].unsqueeze(0))  # (n1, n2, 2)intersection_dims = torch.clamp(upper_bounds - lower_bounds, min=0)  # (n1, n2, 2)return intersection_dims[:, :, 0] * intersection_dims[:, :, 1]  # (n1, n2)def find_jaccard_overlap(set_1, set_2):""" Find the Jaccard Overlap (IoU) of every box combination between two sets of boxes that are in boundary coordinates.:param set_1: set 1, a tensor of dimensions (n1, 4):param set_2: set 2, a tensor of dimensions (n2, 4):return: Jaccard Overlap of each of the boxes in set 1 with respect to each of the boxes in set 2, a tensor of dimensions (n1, n2)"""# Find intersectionsintersection = find_intersection(set_1, set_2)  # (n1, n2)# Find areas of each box in both setsareas_set_1 = (set_1[:, 2] - set_1[:, 0]) * (set_1[:, 3] - set_1[:, 1])  # (n1)areas_set_2 = (set_2[:, 2] - set_2[:, 0]) * (set_2[:, 3] - set_2[:, 1])  # (n2)# Find the union# PyTorch auto-broadcasts singleton dimensionsunion = areas_set_1.unsqueeze(1) + areas_set_2.unsqueeze(0) - intersection  # (n1, n2)return intersection / union  # (n1, n2)

以上代码位于utils.py脚本的find_intersectionfind_jaccard_overlap

3.1.5 小结

以上便是本小节的全部内容了。

本小节我们首先介绍了目标检测的问题背景,随后分析了一个实现目标检测的解决思路,这也是众多经典检测网络和本章要介绍的模型所采用的思路(即先确立众多候选框,再对候选框进行分类和微调)。最后介绍了bbox和IoU这两个目标检测相关的基本概念。

下一小节,我们将会从数据入手,介绍下目标检测领域最常见的一个数据集VOC,以及数据读取相关的代码。

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

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

相关文章

动手学CV-目标检测入门教程2:VOC数据集

3.2 目标检测数据集VOC 本文来自开源组织 DataWhale 🐳 CV小组创作的目标检测入门教程。 对应开源项目 《动手学CV-Pytorch》 的第3章的内容,教程中涉及的代码也可以在项目中找到,后续会持续更新更多的优质内容,欢迎⭐️。 如果…

C语言学习及应用笔记之四:C语言volatile关键字及其使用

在C语言中,还有一个并不经常使用但却非常有用的关键字volatile。那么使用volatile关键字究竟能干什么呢?接下来我将就此问题进行讨论。 一个使用volatile关键字定义变量,其实就是告诉编译系统这变量可能会被意想不到地改变。那么编译时&…

Modbus协议栈开发笔记之三:Modbus TCP Server开发

在完成了前面的工作后,我们就可以实现有针对性的应用了,首先我们来实现Modbus TCP的服务器端应用。当然我们不是做具体的应用,而是对Modbus TCP的服务器端应用进行封装以供有需要时调用。 这里我们不涉及TCP的协议,这部分与Modbu…

动手学CV-目标检测入门教程3:锚框(anchor)

3.3 锚框 or 先验框 本文来自开源组织 DataWhale 🐳 CV小组创作的目标检测入门教程。 对应开源项目 《动手学CV-Pytorch》 的第3章的内容,教程中涉及的代码也可以在项目中找到,后续会持续更新更多的优质内容,欢迎⭐️。 如果使…

动手学CV-目标检测入门教程4:模型结构

3.4 模型结构 本文来自开源组织 DataWhale 🐳 CV小组创作的目标检测入门教程。 对应开源项目 《动手学CV-Pytorch》 的第3章的内容,教程中涉及的代码也可以在项目中找到,后续会持续更新更多的优质内容,欢迎⭐️。 如果使用我们…

PID控制器开发笔记之十二:模糊PID控制器的实现

在现实控制中,被控系统并非是线性时不变的,往往需要动态调整PID的参数,而模糊控制正好能够满足这一需求,所以在接下来的这一节我们将讨论模糊PID控制器的相关问题。模糊PID控制器是将模糊算法与PID控制参数的自整定相结合的一种控…

动手学CV-目标检测入门教程5:损失函数

3.5 损失函数 本文来自开源组织 DataWhale 🐳 CV小组创作的目标检测入门教程。 对应开源项目 《动手学CV-Pytorch》 的第3章的内容,教程中涉及的代码也可以在项目中找到,后续会持续更新更多的优质内容,欢迎⭐️。 如果使用我们…

Modbus协议栈开发笔记之四:Modbus TCP Client开发

这一次我们封装Modbus TCP Client应用。同样的我们也不是做具体的应用,而是实现TCP客户端的基本功能。我们将TCP客户端的功能封装为函数,以便在开发具体应用时调用。 对于TCP客户端我们主要实现的功能有两个:其一是生成访问TCP服务器的命令&…

动手学CV-目标检测入门教程6:训练与测试

3.6、训练与测试 本文来自开源组织 DataWhale 🐳 CV小组创作的目标检测入门教程。 对应开源项目 《动手学CV-Pytorch》 的第3章的内容,教程中涉及的代码也可以在项目中找到,后续会持续更新更多的优质内容,欢迎⭐️。 如果使用我…

PC软件开发技术之一:在WinCC中通过VBS操作SQL Server2005

在项目中需要在一定条件满足时,保存一些数据到数据库中,并可根据条件查询。考虑到WinCC6.2以后采用的就是SQL Server2005数据库,所以直接利用该数据库即可,通过SQL Server Management Studio(SSMS)可以创建…

K 近邻算法(KNN)与KD 树实现

KD树节点 /// <summary>/// &#xff2b;&#xff24;树节点/// /2016/4/1安晟添加/// </summary>[Serializable]public class KDTreeNode{/// <summary>/// 获取或设置节点的空间坐标/// </summary>public double[] Position { get; set; }/// <…

PC软件开发技术之二:用C#开发基于自动化接口的OPC客户端

OPC全称是Object Linking and Embedding&#xff08;OLE&#xff09; for Process Control&#xff0c;它的出现为基于Windows的应用程序和现场过程控制应用建立了桥梁。OPC作为一整套接口、属性和方法的协议标准集&#xff0c;与具体的开发语言没有关系。 1、OPC客户端接口方…

标记符控制的分水岭算法原理及matlab实现

-------------------------------------------------------------------------------------------------------------------- 附录A 教程【3】给出的matlab源码&#xff0c;附详细注释 function [ ] MarkerControlled_Watershed_tutorial( ) %标记符控制的分水岭算法教程 …

PC软件开发技术之三:C#操作SQLite数据库

我们在开发应用是经常会需要用到一些数据的存储&#xff0c;存储的方式有多种&#xff0c;使用数据库是一种比较受大家欢迎的方式。但是对于一些小型的应用&#xff0c;如一些移动APP&#xff0c;通常的数据库过于庞大&#xff0c;而轻便的SQLite则能解决这一问题。不但操作方便…

自动搜索数据增强方法分享——fast-autoaugment

前言 简短的介绍下分享fast-autoaugment的原因 毫无疑问数据增强对于训练CNN非常有效&#xff0c;大家也在不断发明新的数据增强方法 拿到一份数据集&#xff0c;我们凭借之前的经验组合不同的增强方法形成一个数据增强策略&#xff0c;通常可以得到一个还不错的baseline。但…

SSD之硬的不能再硬的硬核解析

本文是对经典论文 SSD: Single Shot MultiBox Detector 的解析&#xff0c;耗时3周完成&#xff0c;万字长文&#xff0c;可能是你能看到的最硬核的SSD教程了&#xff0c;如果想一遍搞懂SSD&#xff0c;那就耐心读下去吧~ 一句话总结SSD效果就是&#xff1a;比YOLO快一点且准很…

C语言学习及应用笔记之五:C语言typedef关键字及其使用

在C语言中有一个typedef关键字&#xff0c;其用来定义用户自定义类型。当然&#xff0c;并不是真的创造了一种数据类型&#xff0c;而是给已有的或者符合型的以及复杂的数据类型取一个我们自己更容易理解的别名。总之&#xff0c;可以使用typedef关键字定义一个我们自己的类型名…

Modbus协议栈开发笔记之五:Modbus RTU Slave开发

Modbus在串行链路上分为Slave和Master&#xff0c;这一节我们就来开发Slave。对于Modbus RTU从站来说&#xff0c;需要实现的功能其实与Modbus TCP的服务器端是一样的。其操作过程也是一样的。首先接收到主站的访问命令&#xff0c;对该命令报文进行解析&#xff0c;这里我们也…

Modbus协议栈开发笔记之六:Modbus RTU Master开发

这一节我们来封装最后一种应用&#xff08;Modbus RTU Master应用&#xff09;&#xff0c;RTU主站的开发与TCP客户端的开发是一致的。同样的我们也不是做具体的应用&#xff0c;而是实现RTU主站的基本功能。我们将RTU主站的功能封装为函数&#xff0c;以便在开发具体应用时调用…

PID控制器开发笔记之十三:单神经元PID控制器的实现

神经网络是模拟人脑思维方式的数学模型。神经网络是智能控制的一个重要分支&#xff0c;人们针对控制过程提供了各种实现方式&#xff0c;在本节我们主要讨论一下采用单神经元实现PID控制器的方式。 1、单神经元的基本原理 单神经元作为构成神经网络的基本单位&#xff0c;具…