【openpcdet中yaml文件的DATA_AUGMENTOR学习】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、代码
  • 二、详细解释
    • DISABLE_AUG_LIST
    • AUG_CONFIG_LIST
      • 1. gt_sampling
      • 2. random_world_flip
      • 3. random_world_rotation
      • 4. random_world_scaling
  • 总结


前言

提示:这里可以添加本文要记录的大概内容:

openpcdet中yaml文件的DATA_AUGMENTOR学习


提示:以下是本篇文章正文内容,下面案例可供参考

一、代码

DATA_AUGMENTOR:DISABLE_AUG_LIST: ['placeholder']AUG_CONFIG_LIST:- NAME: gt_samplingUSE_ROAD_PLANE: TrueDB_INFO_PATH:- kitti_dbinfos_train.pklPREPARE: {filter_by_min_points: ['Car:5', 'Pedestrian:5', 'Cyclist:5'],filter_by_difficulty: [-1],}SAMPLE_GROUPS: ['Car:15','Pedestrian:15', 'Cyclist:15']NUM_POINT_FEATURES: 4DATABASE_WITH_FAKELIDAR: FalseREMOVE_EXTRA_WIDTH: [0.0, 0.0, 0.0]LIMIT_WHOLE_SCENE: False- NAME: random_world_flipALONG_AXIS_LIST: ['x']- NAME: random_world_rotationWORLD_ROT_ANGLE: [-0.78539816, 0.78539816]- NAME: random_world_scalingWORLD_SCALE_RANGE: [0.95, 1.05]

二、详细解释

这个DATA_AUGMENTOR配置主要用于3D目标检测或点云处理的数据增强。

以下是对这段配置的详细解释:

DISABLE_AUG_LIST

'placeholder':这里是一个占位符,表示没有禁用任何数据增强方法。通常,这个列表会包含那些你希望禁用的数据增强方法的名称。

AUG_CONFIG_LIST

这是一个列表,包含了多个数据增强的配置。

1. gt_sampling

NAME: gt_sampling
表示这种数据增强方法的名字是gt_sampling,通常用于从数据库(DB)中采样真值(ground truth)对象并将其放置在场景中。

USE_ROAD_PLANE: True 表示在采样过程中会考虑道路平面。

DB_INFO_PATH:
这是一个列表,包含了数据库信息(如对象的3D边界框、类别等)的路径。在这里,它指向了一个名为kitti_dbinfos_train.pkl的文件。

PREPARE:
filter_by_min_points: 这是一个列表,指定了每个类别对象所需的最小点数。例如,Car:5表示只考虑点数大于或等于5的汽车对象。
filter_by_difficulty: 这是一个列表,指定了过滤对象的难度级别。在这里,-1表示不过滤任何难度级别的对象。
SAMPLE_GROUPS: 这是一个列表,指定了每个类别对象在场景中应该被采样的数量。例如,Car:15表示应该采样15个汽车对象。

NUM_POINT_FEATURES: 表示每个点云点的特征数量,这里是4个。

DATABASE_WITH_FAKELIDAR: False 表示不使用模拟的激光雷达数据。

REMOVE_EXTRA_WIDTH: 一个列表,指定了在采样对象时从对象的边界框中移除的额外宽度(以x, y, z方向为顺序)。在这里,没有移除任何额外宽度。

LIMIT_WHOLE_SCENE: False 表示不限制整个场景的大小或内容。

2. random_world_flip

NAME: random_world_flip 表示这种数据增强方法的名字是随机翻转整个世界场景。

ALONG_AXIS_LIST: [‘x’] 表示只在x轴方向上进行随机翻转。

当采用random_world_flip这种数据增强方法后,数据会发生以下改变:

方向性变化:

原本的三维场景或对象会在指定的轴上(如x轴)进行随机翻转。这意味着场景或对象的方向会发生变化,可能是向左翻、向右翻,或者是上下翻转(如果沿z轴翻转)。

标签和注释的相应调整:

如果场景或对象带有标签或注释(例如目标检测任务中的边界框或语义分割任务中的语义标签),那么这些标签和注释也需要进行相应的翻转调整,以确保它们仍然正确地与翻转后的场景或对象对应。

数据多样性的增加:

通过随机翻转,原始数据集中的每个场景或对象都会产生多个不同方向的变体,从而增加了数据的多样性。这有助于训练出更加鲁棒和泛化能力更强的模型。

def random_world_flip(self, data_dict=None, config=None):if data_dict is None:return partial(self.random_world_flip, config=config)gt_boxes, points = data_dict['gt_boxes'], data_dict['points']for cur_axis in config['ALONG_AXIS_LIST']:assert cur_axis in ['x', 'y']gt_boxes, points, enable = getattr(augmentor_utils, 'random_flip_along_%s' % cur_axis)(gt_boxes, points, return_flip=True)data_dict['flip_%s'%cur_axis] = enableif 'roi_boxes' in data_dict.keys():num_frame, num_rois,dim = data_dict['roi_boxes'].shaperoi_boxes, _, _ = getattr(augmentor_utils, 'random_flip_along_%s' % cur_axis)(data_dict['roi_boxes'].reshape(-1,dim), np.zeros([1,3]), return_flip=True, enable=enable)data_dict['roi_boxes'] = roi_boxes.reshape(num_frame, num_rois,dim)data_dict['gt_boxes'] = gt_boxesdata_dict['points'] = pointsreturn data_dict
gt_boxes, points, enable = getattr(augmentor_utils, 'random_flip_along_%s' % cur_axis)(gt_boxes, points, return_flip=True)  

这段代码定义了一个名为random_world_flip的函数,它用于对三维点云数据及其对应的标签(通常是目标边界框)进行随机的轴翻转。

以下是对该代码的详细解释:

函数定义

def random_world_flip(self, data_dict=None, config=None):
self: 表示这是一个类的方法,可能是一个数据增强类的一部分。
data_dict: 一个字典,包含点云数据(points)和对应的目标边界框(gt_boxes)等信息。
config: 一个配置字典,其中包含了翻转时要考虑的轴列表(ALONG_AXIS_LIST)。

主体部分
参数检查

if data_dict is None:  return partial(self.random_world_flip, config=config)
如果data_dict是None,则返回一个偏函数(partial function),该函数在稍后可以被调用,并自动传入config参数。

数据遍历和翻转

for cur_axis in config['ALONG_AXIS_LIST']:  
...
遍历配置中指定的轴列表,对每个轴进行翻转操作。

翻转断言

assert cur_axis in ['x', 'y']
确保当前轴只能是'x'或'y'。这通常是因为在三维空间中,沿z轴翻转可能不符合物理世界的情况(如重力方向)。

调用翻转函数

gt_boxes, points, enable = getattr(augmentor_utils, 'random_flip_along_%s' % cur_axis)(  gt_boxes, points, return_flip=True  
)
使用getattr从augmentor_utils模块中动态获取翻转函数(如random_flip_along_x或random_flip_along_y),并传入gt_boxes、points和return_flip=True。该函数会对数据进行翻转,并返回翻转后的数据以及一个布尔值enable,表示是否实际进行了翻转。

def random_flip_along_x(gt_boxes, points, return_flip=False, enable=None):"""Args:gt_boxes: (N, 7 + C), [x, y, z, dx, dy, dz, heading, [vx], [vy]]points: (M, 3 + C)Returns:"""if enable is None:enable = np.random.choice([False, True], replace=False, p=[0.5, 0.5])if enable:gt_boxes[:, 1] = -gt_boxes[:, 1]gt_boxes[:, 6] = -gt_boxes[:, 6]points[:, 1] = -points[:, 1]if gt_boxes.shape[1] > 7:gt_boxes[:, 8] = -gt_boxes[:, 8]if return_flip:return gt_boxes, points, enablereturn gt_boxes, points

这段代码定义了一个函数 random_flip_along_x,用于沿x轴随机翻转三维数据(如点云和目标边界框)。

下面是对该代码的详细解释:

函数定义

def random_flip_along_x(gt_boxes, points, return_flip=False, enable=None):
gt_boxes: 是一个形状为 (N, 7 + C) 的二维数组,其中N表示目标边界框的数量,7表示每个边界框的基本属性(x, y, z, dx, dy, dz, heading),C表示额外的属性(如速度vx, vy等)。points: 是一个形状为 (M, 3 + C) 的二维数组,其中M表示点的数量,3表示每个点的三维坐标(x, y, z),C表示额外的属性。return_flip: 一个布尔值,如果为True,则除了返回翻转后的gt_boxes和points外,还返回是否执行了翻转的标志enable。enable: 一个布尔值,如果传入,则指定是否执行翻转。如果为None,则随机决定是否执行翻转。

函数体

随机决定是否翻转

if enable is None:  enable = np.random.choice([False, True], replace=False, p=[0.5, 0.5])
如果enable是None,则使用numpy的random.choice函数随机选择是否执行翻转。默认情况下,翻转和不翻转的概率都是0.5。

执行翻转

if enable:  gt_boxes[:, 1] = -gt_boxes[:, 1]  gt_boxes[:, 6] = -gt_boxes[:, 6]  points[:, 1] = -points[:, 1]  if gt_boxes.shape[1] > 7:  gt_boxes[:, 8] = -gt_boxes[:, 8]

如果决定执行翻转:

边界框的y坐标(索引为1)被取反,实现沿x轴的翻转。边界框的heading(索引为6)也被取反,因为heading通常表示目标的朝向,翻转后朝向也会变化。点的y坐标(索引为1)也被取反。如果gt_boxes有额外的属性(即C > 0),并且第一个额外属性是速度vy(通常索引为8),则也将其取反(这取决于额外的属性是否表示速度,并且vy是否是第一个)。

返回结果

if return_flip:  return gt_boxes, points, enable  
return gt_boxes, points
根据return_flip的值决定是否返回enable。如果return_flip为True,则返回翻转后的gt_boxes、points和enable;否则只返回翻转后的gt_boxes和points。

总结
这个函数允许你沿x轴随机翻转三维数据(如点云和目标边界框),并可以返回是否执行了翻转的标志。这在数据增强中很有用,可以帮助训练出更鲁棒的模型。


记录翻转状态

data_dict[‘flip_%s’%cur_axis] = enable

将翻转状态记录到data_dict中,以便后续处理。

处理ROI(Region of Interest)边界框、

如果data_dict中包含'roi_boxes'键,则对ROI边界框也进行相同的翻转操作。这里,ROI边界框可能是在多帧数据或特定区域中定义的边界框。

更新数据字典

data_dict['gt_boxes'] = gt_boxes  
data_dict['points'] = points
最后,将翻转后的gt_boxes和points更新回data_dict中。

返回值

函数返回更新后的data_dict。

总结

这个函数实现了对三维点云数据和目标边界框的随机轴翻转,同时考虑了ROI边界框的翻转,并将翻转状态记录到数据字典中。这种数据增强方法有助于提高三维目标检测或场景理解模型的泛化能力

3. random_world_rotation

NAME: random_world_rotation 表示这种数据增强方法的名字是随机旋转整个世界场景。

WORLD_ROT_ANGLE: [-0.78539816, 0.78539816] 表示旋转角度的范围,单位是弧度。这个范围大约对应于-45度到45度。

def global_rotation(gt_boxes, points, rot_range, return_rot=False, noise_rotation=None):"""Args:gt_boxes: (N, 7 + C), [x, y, z, dx, dy, dz, heading, [vx], [vy]]points: (M, 3 + C),rot_range: [min, max]Returns:"""if noise_rotation is None: noise_rotation = np.random.uniform(rot_range[0], rot_range[1])points = common_utils.rotate_points_along_z(points[np.newaxis, :, :], np.array([noise_rotation]))[0]gt_boxes[:, 0:3] = common_utils.rotate_points_along_z(gt_boxes[np.newaxis, :, 0:3], np.array([noise_rotation]))[0]gt_boxes[:, 6] += noise_rotationif gt_boxes.shape[1] > 7:gt_boxes[:, 7:9] = common_utils.rotate_points_along_z(np.hstack((gt_boxes[:, 7:9], np.zeros((gt_boxes.shape[0], 1))))[np.newaxis, :, :],np.array([noise_rotation]))[0][:, 0:2]if return_rot:return gt_boxes, points, noise_rotationreturn gt_boxes, points

这段代码定义了一个名为 global_rotation 的函数,其主要目的是对给定的 gt_boxes(真实边界框)和
points(点云数据)进行全局旋转。这里的旋转是沿着 z 轴进行的。

下面是详细的解释:

输入参数:

gt_boxes: 一个形状为 (N, 7 + C) 的数组,其中 N 是边界框的数量,7 是边界框的基本属性(x, y, z, dx, dy, dz, heading),C 是可选的额外属性(如速度 vx, vy)。points: 一个形状为 (M, 3 + C) 的数组,其中 M 是点的数量,3 是点的三维坐标(x, y, z),C 是可选的额外属性。rot_range: 一个长度为 2 的列表,表示旋转角度的范围(即 [min, max])。return_rot: 一个布尔值,决定是否返回旋转角度。noise_rotation: 可选的旋转角度,如果为 None,则随机从 rot_range 中选择一个。

函数执行:
如果 noise_rotation 为 None,则从 rot_range 中随机选择一个旋转角度。

使用 common_utils.rotate_points_along_z 函数对 points 进行旋转。这个函数会沿着 z 轴旋转点云数据,并返回旋转后的结果。同样地,使用 common_utils.rotate_points_along_z 函数对 gt_boxes 的前三维(x, y, z)进行旋转,并更新 gt_boxes。更新 gt_boxes 的 heading(方向角)属性,将其加上 noise_rotation。如果 gt_boxes 有额外的属性(如速度 vx, vy),并且这些属性是二维的(可能是速度向量),则也对它们进行旋转。根据 return_rot 的值,决定是否返回旋转角度 noise_rotation。

输出:

如果 return_rot 为 True,则返回旋转后的 gt_boxes、points 和旋转角度 noise_rotation。如果 return_rot 为 False(或省略),则只返回旋转后的 gt_boxes 和 points。

这个函数在三维目标检测或点云处理中可能很有用,特别是当你需要模拟真实世界中的旋转或对数据集进行增强时。

4. random_world_scaling

NAME: random_world_scaling 表示这种数据增强方法的名字是随机缩放整个世界场景。

WORLD_SCALE_RANGE: [0.95, 1.05] 表示缩放因子的范围。这意味着场景可以被缩放到原始大小的95%到105%之间。

def global_scaling(gt_boxes, points, scale_range, return_scale=False):"""Args:gt_boxes: (N, 7), [x, y, z, dx, dy, dz, heading]points: (M, 3 + C),scale_range: [min, max]Returns:"""if scale_range[1] - scale_range[0] < 1e-3:return gt_boxes, pointsnoise_scale = np.random.uniform(scale_range[0], scale_range[1])points[:, :3] *= noise_scalegt_boxes[:, :6] *= noise_scaleif gt_boxes.shape[1] > 7:gt_boxes[:, 7:] *= noise_scaleif return_scale:return gt_boxes, points, noise_scalereturn gt_boxes, points

这段代码定义了一个名为global_scaling的函数,其主要功能是对给定的点云(points)和地面真值边界框(gt_boxes)进行全局缩放。缩放的比例(noise_scale)是从指定的缩放范围(scale_range)中随机选择的。

以下是该函数的详细解释:

参数

gt_boxes: 形状为 (N, 7) 的数组,其中 N 是边界框的数量。每个边界框有7个元素,分别是 [x, y, z, dx, dy, dz, heading]。其中 (x, y, z) 是边界框的中心坐标,(dx, dy, dz) 是边界框的尺寸(宽度、长度和高度),而 heading 是边界框的朝向。points: 形状为 (M, 3 + C) 的数组,其中 M 是点的数量,3 表示每个点的三维坐标 (x, y, z),C 表示每个点的其他特征数量(如果有的话)。scale_range: 一个长度为2的列表或数组,表示缩放比例的取值范围,即 [min, max]。return_scale: 一个布尔值,如果为 True,则函数还会返回缩放比例 noise_scale。

返回值

如果 return_scale 为 False,则返回缩放后的 gt_boxes 和 points。如果 return_scale 为 True,则返回缩放后的 gt_boxes、points 和缩放比例 noise_scale。	

功能

检查缩放范围:如果 scale_range 的两个值之间的差小于 1e-3(即缩放范围非常小),则不进行任何操作并直接返回原始的 gt_boxes 和 points。随机选择缩放比例:从 scale_range 中随机选择一个缩放比例 noise_scale。缩放点云:将 points 数组中的每个点的三维坐标 (x, y, z) 乘以缩放比例 noise_scale。缩放边界框:将 gt_boxes 数组中的每个边界框的中心坐标 (x, y, z) 和尺寸 (dx, dy, dz) 乘以缩放比例 noise_scale。如果 gt_boxes 的列数大于7(即存在额外的特征或属性),则这些额外的特征或属性也会被缩放。返回结果:根据 return_scale 的值,返回缩放后的 gt_boxes、points 和(可选的)缩放比例 noise_scale。

总结

总的来说,这个DATA_AUGMENTOR配置定义了一系列数据增强方法,这些方法可以帮助模型更好地泛化并处理各种复杂的场景和对象。

在训练3D目标检测模型时,使用这些数据增强方法通常可以提高模型的性能和鲁棒性。

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

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

相关文章

多线程(八)

一、wait和notify 等待 通知 机制 和join的用途类似,多个线程之间随机调度,引入 wait notify 就是为了能够从应用层面上,干预到多个不同线程代码的执行顺序.( 这里说的干预,不是影响系统的线程调度策略 内核里的线程调度,仍然是无序的. 相当于是在应用程序…

Pod容器资源限制和探针

目录 一、资源限制 1.Pod和容器的资源请求和限制 2.CPU 资源单位 案例一 案例二 二、健康检查&#xff0c;又称为探针&#xff08;Probe&#xff09; 1.探针的三种规则 2.Probe支持三种检查方法 3.探测获得的三种结果 案例一&#xff1a;exec 案例二&#xff1a;htt…

OneMO同行 心级服务:中移物联OneMO模组助力客户终端寒冷环境下的稳定运行

中移物联OneMO模组以客户为中心&#xff0c;基于中国移动心级服务要求&#xff0c;开展“OneMO同行 心级服务 标定一流”高标服务主题活动&#xff0c;升级“服务内容““服务方式”和“服务意识”&#xff0c;为行业客户提供全新的服务体验。 近日&#xff0c;某车载监控设备…

Hive语法学习总结

Hive SQL语法学习总结 hive参数库操作1.创建库2.具体案例3.库的其他操作 表和库的路径演示表的操作创建表插入数据 hive参数 一 hive常用交互命令hive -e sql语句hive -f sql文件 //文件中是sql语句二 参数的设置方式一&#xff1a;在客户端中设置参数(当次有效)set 参数名参…

ACM实训第十七天

Is It A Tree? 问题 考试时应该做不出来&#xff0c;果断放弃 树是一种众所周知的数据结构&#xff0c;它要么是空的(null, void, nothing)&#xff0c;要么是一个或的集合满足以下属性的节点之间有向边连接的节点较多。 •只有一个节点&#xff0c;称为根节点&#xff0c;它…

【Crypto】摩丝

文章目录 一、摩斯解题感悟 一、摩斯 很明显莫尔斯密码 iloveyou还挺浪漫 小小flag&#xff0c;拿下 解题感悟 莫尔斯密码这种题还是比较明显的

【董晓算法】竞赛常用知识之图论3(最近公共祖先)

前言&#xff1a; 本系列是学习了董晓老师所讲的知识点做的笔记 董晓算法的个人空间-董晓算法个人主页-哔哩哔哩视频 (bilibili.com) 动态规划系列&#xff08;还没学完&#xff09; 【董晓算法】动态规划之线性DP问题-CSDN博客 【董晓算法】动态规划之背包DP问题&#xff…

智能锁千千万,谁是你的NO.1,亲身实测凯迪仕传奇大师K70旗舰新品

智能锁千千万&#xff0c;谁是你的NO.1。欢迎来到智哪儿评测室&#xff0c;这次我们为大家带来了凯迪仕传奇大师K70系列的一款重磅新品。 在科技的浪潮中&#xff0c;家居安全领域正经历着前所未有的变革。智能锁越来越成为家的安全守护神&#xff0c;以及智能生活的得力助手。…

Android 11 Framework实时监听Activity堆栈变化

核心类 Framework中有一个类SystemActivityMonitoringService专门用于监控Activity堆栈变化&#xff0c;属于隐藏Api&#xff0c;应用侧无法调用。此类位于 packages/services/Car/service/src/com/android/car/SystemActivityMonitoringService.java 方法 void registerTa…

Mysql信息脱敏

类似微信姓名脱敏&#xff1a; SELECT CONCAT( REPEAT(*, CHAR_LENGTH(real_name) -1 ), RIGHT(real_name, 1) ) name from user_info电话号脱敏&#xff1a; SELECT CONCAT(LEFT(mobile_phone, 3), REPEAT(*, 4 ), RIGHT(mobile_phone, 4) ) phone from user_info

大数据Hive中的UDF:自定义数据处理的利器(下)

在上一篇文章中&#xff0c;我们对第一种用户定义函数&#xff08;UDF&#xff09;进行了基础介绍。接下来&#xff0c;本文将带您深入了解剩余的两种UDF函数类型。 文章目录 1. UDAF1.1 简单UDAF1.2 通用UDAF 2. UDTF3. 总结 1. UDAF 1.1 简单UDAF 第一种方式是 Simple(简单…

每日一题《leetcode--382.链表随机结点》

https://leetcode.cn/problems/linked-list-random-node/ 这道题我们首先看到题目中的要求&#xff1a;在单链表中随机选取一个链表中的结点&#xff0c;要使每个结点被选取的概率是一样的。 当我们看到随机这两个字时&#xff0c;应该就会想起rand()这个函数。接着我们把使用这…

[晕事]今天做了件晕事35 VM发送给gateway太多ARP,导致攻击检查?

最近遇到一个问题&#xff0c;说网关学不到新起来VM的mac地址&#xff0c;通过tshark抓包发现&#xff0c;VM已经发出去GARP了。而且连续发送了24个GARP。 就认为是网关的问题&#xff0c;为什么没网关没有学到&#xff1f;就让测试同事开网络设备的ticket。 后来听同事说&…

自己搭建内网穿透

本文介绍使用最新版frp搭建内网穿透&#xff0c;最新版本的frp在配置上与之前有很大不同&#xff0c;需要使用.toml文件进行配置。其中主要问题出现在toml文件内部。 一、云服务器配置 下载frp sudo apt update sudo apt install wget wget https://github.com/fatedier/frp…

求出这行英文中最后一个单词的长度

【题目描述】蓝宝看到了一行奇怪的英文&#xff0c;这行英文由若干单词组成&#xff0c;每个单词前后用一些字符*隔开请帮助蓝宝求出这行英文中最后一个单词的长度。【输入格式】 输入一行&#xff0c;就就是蓝宝看到的奇怪的英文。 【输出格式】 输出一行&#xff0c;是个整数…

文旅3d仿真数字人形象为游客提供全方位的便捷服务

在AI人工智能与VR虚拟现实技术的双重驱动下&#xff0c;文旅3D数字代言人正以其独特的魅力&#xff0c;频频亮相于各类文旅场景&#xff0c;为游客带来前所未有的个性化服务体验。他们不仅有趣有品&#xff0c;更能言善道&#xff0c;成为文旅业数字化发展的新亮点。 这些文旅3…

Android 文件加密解密(AES)

private static final String ALGORITHM "AES"; 文件加密 /*** 文件加密* param secretKey 文件加密密钥* param oldFiles 原始文件列表&#xff0c;需要加密的* param newFiles 构造加密后的文件列表*&#xff08;选择多个或者单个&#xff09;多个文件加密*/ Re…

我的文章分类合集目录

文章目录 Java相关基础常规问题类Docker类RabbitMQ类分库分表 网络工程相关路由交换、Cisco Packet TracerIP地址 前端相关数据库 Java相关 基础 Java开发规范、项目开发流程 SpringBoot整合MyBatis实现增删改查(简单,详细) SpringBoot整合MybatisPlus&#xff08;详细&#…

【Muduo】TcpConnection类

Muduo网络库的TcpConnection类代表了TCP连接的一端&#xff0c;即服务器与远程对等端之间的连接。TcpConnection类知道自身和对端的InetAddress、封装了前面讲过的Socket类和Channel类&#xff0c;并且保有管理自己的subLoop指针&#xff0c;还有多种事件处理函数和回调&#x…

【搜索】BFS

#include <iostream> #include <cstring> #include <queue>using namespace std;const int N 110;typedef pair<int, int> PII;int n, m; int g[N][N], d[N][N];//存放地图//存每一个点到起点的距离int bfs() {queue< PII > q;q.push({0, 0});m…