网站首页 > 技术文章 正文
随着AR / VR,自动驾驶汽车的发展,3D视觉问题变得越来越重要,因为它提供了比2D更丰富的信息。我将介绍两种基本的3D场景分析深度学习模型,VoxNet和PointNet。
3D格式简介
3D图像测量更多维度,即深度维度。有两种最广泛使用的3D格式,即RGB-D和点云(point cloud)。对于正常的基于像素的图像,我们可以通过(x,y)坐标定位任何像素,然后我们可以分别获得三个属性(R,G,B)。而在RGB-D图像中,每个(x,y)坐标将对应于四个属性(depth,R,G,B)。RGB-D和点云之间唯一的区别在于,在点云中,(x,y)坐标反映了真实世界中的实际值,而不是简单的整数值。
此外,如果您有一个RGB-D扫描,并且还了解您的扫描相机的内部特性,您将能够通过使用camera intrinsic简单地计算真实世界(x, y),从RGB-D图像创建点云。这叫做相机标定(camera intrinsics)。因此,到目前为止,您应该知道RGB-D图像是网格对齐的图像,而点云的结构更为稀疏。
3D Vision
就像二维问题一样,我们想要检测和识别3D扫描中的所有对象。与2D图像不同,输入数据以使用CNNs的最佳方式是什么?
Voxel Grid
Voxel Grid是最直观的方法,它将3D对象嵌入到网格中,使其看起来像像素图像,而我们在这里称之为Voxel(体素) 。在这种情况下,3D图像用(x, y, z)坐标来描述,就像乐高一样。
VoxNet是一种基于深度学习的架构,用于使用占用网格对三维点云进行分类,这在分类问题上非常有效。
例如,如果我们将点云拟合到32x32x32 Voxel Grid,我们可以构建一个填充零的32x32x32数组。然后缩放点云以计算每个小Voxel内有多少个点。
获得体素网格后,我们将接下来执行3D卷积,这有效地将立方体滑过基于体素的图像。
我们正在将我们的扫描扩展到相同的基础上。我们可以想象,如果我们有一个大规模的扫描,每个对象将只是一个会导致一些问题的体素。而且,由于这些上采样操作,要确定每个体素的RGB颜色并不容易。
对于简单的数据集(具有相似的点数,类似的扫描规模),VoxNet可能是一种简单而好的方法。但是如果遇到一个复杂的数据集,它可能不是一个好的选择。
Points
虽然基于体素的方法在分类问题上可以很好地工作,但它为上采样行为牺牲了大量信息。因此,我们可能想要明智地训练我们的网络。
第一个问题是点的顺序,我们知道点云对点的顺序是不变的。处理这个问题有三种策略(PointNet):
- 对点进行排序。
- 作为RNN序列输入,通过用各种排列来扩充序列。
- 使用一个对称函数来聚合每个点的信息。说到对称函数,我们指的是像+或*这样的对称二元函数。
在PointNet的论文中,他们说第一种方法是位计算强度,第二种方法不够健壮。因此,使用了一个对称函数max pooling。最大池是这里的主要操作。
整个体系结构如下所示,
通常,它是灵活使用卷积,全连接和最大池化层。我发现首先可能很难理解,所以让我们通过代码来看看它。
首先,我将给出一个示例点云,代表每行的(x,y,z,r,g,b)。每一行代表这里的一点。假设我们在这个例子中有n点。
...
-38. 17. 54. 149 148 147
-38. 89. 54. 152 153 152
-79. 99. 32. 151 151 148
...
注意:PointNet的实际输入使用标准化的RGB颜色,并且x,y值的基点在空间中心对齐。我没有这样做,只是为了不弄乱浮点数。
PointNet中的分类
第一个操作是进行2d卷积,内核大小(1,6)将一个点的相关信息(x,y,z,r,g,b;共6个)聚合在一起。这里的输出应该是(n,1,64)。
net = tf_util.conv2d(input_image, 64, [1,6], padding='VALID', stride=[1,1], scope='conv1')
注意:每层都有批量标准化,我将其删除以简化演示。另外,原始的pointnet使用9个特征作为输入(x,y,z,r,g,b,normalized_x,normalized_y,normalized_z)。
然后会有几个1x1卷积运算来像素明智地检测这些小特征。因此,我们将在数组大小为(n,1,1024)。
net = tf_util.conv2d(net, 64, [1,1], padding='VALID', stride=[1,1], scope='conv2')
net = tf_util.conv2d(net, 64, [1,1], padding='VALID', stride=[1,1], scope='conv3')
net = tf_util.conv2d(net, 128, [1,1], padding='VALID', stride=[1,1], scope='conv4')
points_feat1 = tf_util.conv2d(net, 1024, [1,1], padding='VALID', stride=[1,1], scope='conv5')
接下来最重要的步骤是,最大池选择所有点中最特别的特性。这就是为什么函数是不变量的原因。由于我们在以前的层中有1024个过滤器,所以这个层将输出1024个特性。
pc_feat1 = tf_util.max_pool2d(points_feat1, [n,1], padding='VALID', scope='maxpool1')
然后所有功能都将通过全连接层完全连接。
pc_feat1 = tf.reshape(pc_feat1, [batch_size, -1])
pc_feat1 = tf_util.fully_connected(pc_feat1, 256, bn=True, scope='fc1')
pc_feat1 = tf_util.fully_connected(pc_feat1, 128, bn=True, scope='fc2')
注意:在我们的例子中,批大小是1。而PointNet的输入是对场景的扫描,将被分成小批(每批4096个点)。PointNet将执行特性检测批处理
到目前为止,您可以回到上面的图中,如果您添加一个全连接层来输出类标签的数量,这就是PointNet在点云上进行分类的方式。简单地说,
- 要聚合每个点信息,
- 为了找到每个点最特别的特征,
- 然后fully-connect分类。
PointNet中的语义分割
分割部分是分类模型的一种不断发展。但是,我们希望网络能够忽略点的顺序。因此,我们将每个点要素与“全局特性”连接起来,让每个要点知道上下文。
pc_feat1_reshape = tf.reshape(pc_feat1, [batch_size, 1, 1, -1])
pc_feat1_expand = tf.tile(pc_feat1_reshape, [1, num_point, 1, 1])
points_feat1_concat = tf.concat(axis=3, values=[points_feat1, pc_feat1_expand])
然后,我们将使用几个1x1卷积核来提取新的点向量特征。
net = tf_util.conv2d(points_feat1_concat, 512, [1,1], padding='VALID', stride=[1,1], scope='conv6')
net = tf_util.conv2d(net, 256, [1,1], padding='VALID', stride=[1,1], scope='conv7')
然后我们可以做出明智的预测。例如,每个点有13个类。
net = tf_util.conv2d(net, 13, [1,1], padding='VALID', stride=[1,1], activation_fn=None, scope='conv8')
猜你喜欢
- 2024-09-27 后端思维篇:如何抽一个观察者模板
- 2024-09-27 使用Hourglass网络来理解人体姿态
- 2024-09-27 SM框架整合篇 ssm框架crud
- 2024-09-27 动物分类器 动物分类网
- 2024-09-27 图表显示日志离线信息 离线日志正在运行
- 2024-09-27 比用Pytorch框架快200倍!0.76秒后,笔记本上的CNN就搞定了MNIST
- 2024-09-27 卷积神经网络背后的数学 卷积神经网络教学视频
- 2024-09-27 多层级遇到多兴趣:快手、武汉大学用于序列推荐的多粒度神经模型
- 2024-09-27 使用分割来寻找疑似结节(13) 分割检测
- 2024-09-27 买药秒送 JADE动态线程池实践及原理浅析
你 发表评论:
欢迎- 最近发表
-
- 在 Spring Boot 项目中使用 activiti
- 开箱即用-activiti流程引擎(active 流程引擎)
- 在springBoot项目中整合使用activiti
- activiti中的网关是干什么的?(activiti包含网关)
- SpringBoot集成工作流Activiti(完整源码和配套文档)
- Activiti工作流介绍及使用(activiti工作流会签)
- SpringBoot集成工作流Activiti(实际项目演示)
- activiti工作流引擎(activiti工作流引擎怎么用)
- 工作流Activiti初体验及在数据库中生成的表
- Activiti工作流浅析(activiti6.0工作流引擎深度解析)
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)