2、PF-Net点云补全

news2024/9/21 10:50:56

2、PF-Net 点云补全

PF-Net论文链接:PF-Net

PF-NetPoint Fractal Network for 3D Point Cloud Completion)是一种专门为三维点云补全设计的深度学习模型。

点云补全实际上和图片补全是一个逻辑,都是采用GAN模型的思想来进行补全,在图片补全中,将部分像素点删除并且标记,然后卷积特征提取预测、判别器判别,来训练模型,生成的像素点与原来像素点比较完成模型的训练。而PF-Net就是采用GAN的思想在3D点云上的应用。

模型架构

**Multi-Resolution Encoder(MRE):**编码器,PF-Net在特征提取方面,在PointNet的基础上进行了改进,在不同层面进行采样,但是与PointNet++的多层面采样不一样,PF-Net没有像PointNet++一样提取某个点周围的点的特征,进行分组提取特征,而是采用最远距离采样,选取不同个个数的采样点,从细节到轮廓多层次采样,其次在进行卷积时,对于PointNet只在最后一层进行maxpooling来获得最终特征值,但是PF-Net则在提取的过程中,在卷积提取过程中,对卷积结果进行maxpooling提取特征,最终将多次maxpooling提取到的特征拼接,使特征既有轮廓信息,又有细节信息。

**Point Pyramid Deconder(PPD):**解码器,在进行预测时,先是预测出一个轮廓,再将轮廓信息加入到下面,逐级预测更多的细节,慢慢加入特征,使预测更急准确。

**Discriminator:**判別器,与GAN中的判别器逻辑一模一样,有两组输入,对比是否预测准确,实际上就是做了一个二分类,输出每个点结果为True或False,表示预测是否正确。

对于训练参数的更新,主要CD和判别器的Loss,CD计算的是每个预测点和距离他最近的正确点的距离,同时正确的点也会和预测点计算CD值,获得Loss值,更新参数。

模型架构图

在这里插入图片描述

数据准备
for i, data in enumerate(dataloader, 0): 
    real_point, target = data  # 从dataloader中获取真实的点云数据和对应的目标标签
    
    batch_size = real_point.size()[0]  # 获取批量大小
    real_center = torch.FloatTensor(batch_size, 1, opt.crop_point_num, 3)  # 初始化用于存储被裁剪的点
    print(real_center.shape)  # 输出 real_center 的形状
    input_cropped1 = torch.FloatTensor(batch_size, opt.pnum, 3)  # 初始化裁剪后的输入点云数据
    print(input_cropped1.shape)  # 输出 input_cropped1 的形状 ([4, 2048, 3])
    
    # 将 real_point 复制到 input_cropped1 中
    input_cropped1 = input_cropped1.data.copy_(real_point)
    print(input_cropped1.shape)  # 输出复制后的 input_cropped1 的形状 ([4, 2048, 3])
    
    # 添加一个维度到 real_point,方便之后的操作
    real_point = torch.unsqueeze(real_point, 1)
    print(real_point.shape)  # 输出添加维度后的形状 ([4, 1, 2048, 3])
    
    # 添加一个维度到 input_cropped1,方便之后的操作
    input_cropped1 = torch.unsqueeze(input_cropped1,1)
    print(input_cropped1.shape)  # 输出添加维度后的 input_cropped1 的形状

    p_origin = [0,0,0]  # 设置原点位置
    
    # 根据不同的裁剪方法裁剪点云
    if opt.cropmethod == 'random_center':
        # 设置随机视角的选项
        choice = [torch.Tensor([1,0,0]), torch.Tensor([0,0,1]), torch.Tensor([1,0,1]), torch.Tensor([-1,0,0]), torch.Tensor([-1,1,0])]
        for m in range(batch_size):
            # 从选择中随机选取一个视角
            index = random.sample(choice,1)
            distance_list = []
            p_center = index[0]  # 选取的视角作为中心点
            for n in range(opt.pnum):
                # 计算每个点与中心点之间的距离
                distance_list.append(distance_squre(real_point[m,0,n], p_center))
            
            # 将距离排序,得到每个点的索引和值
            distance_order = sorted(enumerate(distance_list), key=lambda x: x[1])
            print(distance_order)  # 输出距离排序
            
            # 裁剪掉距离中心点最近的 opt.crop_point_num 个点
            for sp in range(opt.crop_point_num):
                input_cropped1.data[m, 0, distance_order[sp][0]] = torch.FloatTensor([0,0,0])  # 用 [0,0,0] 替换裁剪掉的点
                real_center.data[m, 0, sp] = real_point[m, 0, distance_order[sp][0]]  # 保存被裁剪的点到 real_center 中

    # 重新调整标签的大小并赋值
    label.resize_([batch_size, 1]).fill_(real_label)
    print(label.shape)  # 输出标签的形状

    # 将数据移到 GPU 设备上
    real_point = real_point.to(device)
    real_center = real_center.to(device)
    input_cropped1 = input_cropped1.to(device)
    label = label.to(device)

    ############################
    # (1) 准备数据
    ############################
    
    # 将 real_center 设置为可求导变量
    real_center = Variable(real_center, requires_grad=True)
    real_center = torch.squeeze(real_center, 1)  # 去除多余的维度
    
    # 通过最远点采样算法从 real_center 中选取64个关键点
    real_center_key1_idx = utils.farthest_point_sample(real_center, 64, RAN=False)
    real_center_key1 = utils.index_points(real_center, real_center_key1_idx)
    real_center_key1 = Variable(real_center_key1, requires_grad=True)  # 设置为可求导变量
    print(real_center_key1.shape)  # 输出关键点的形状

    # 通过随机最远点采样算法从 real_center 中选取128个关键点
    real_center_key2_idx = utils.farthest_point_sample(real_center, 128, RAN=True)
    real_center_key2 = utils.index_points(real_center, real_center_key2_idx)
    real_center_key2 = Variable(real_center_key2, requires_grad=True)  # 设置为可求导变量
    print(real_center_key2.shape)  # 输出关键点的形状

    # 去除 input_cropped1 的多余维度
    input_cropped1 = torch.squeeze(input_cropped1, 1)
    print(input_cropped1.shape)  # 输出去除维度后的形状

    # 从 input_cropped1 中采样不同数量的点
    input_cropped2_idx = utils.farthest_point_sample(input_cropped1, opt.point_scales_list[1], RAN=True)
    input_cropped2 = utils.index_points(input_cropped1, input_cropped2_idx)
    
    input_cropped3_idx = utils.farthest_point_sample(input_cropped1, opt.point_scales_list[2], RAN=False)
    input_cropped3 = utils.index_points(input_cropped1, input_cropped3_idx)
    
    # 将裁剪后的点云设置为可求导变量
    input_cropped1 = Variable(input_cropped1, requires_grad=True)
    print(input_cropped1.shape)  # 输出裁剪后的 input_cropped1 形状
    
    input_cropped2 = Variable(input_cropped2, requires_grad=True)
    print(input_cropped2.shape)  # 输出裁剪后的 input_cropped2 形状
    
    input_cropped3 = Variable(input_cropped3, requires_grad=True)
    print(input_cropped3.shape)  # 输出裁剪后的 input_cropped3 形状
    
    # 将裁剪后的数据移到 GPU 设备上
    input_cropped2 = input_cropped2.to(device)
    input_cropped3 = input_cropped3.to(device)

    # 将不同尺度的裁剪数据保存到列表中
    input_cropped = [input_cropped1, input_cropped2, input_cropped3]

Multi-Resolution Encoder(MRE)

**Multi-Resolution Encoder(MRE):**编码器,PF-Net在特征提取方面,在PointNet的基础上进行了改进,在不同层面进行采样,但是与PointNet++的多层面采样不一样,PF-Net没有像PointNet++一样提取某个点周围的点的特征,进行分组提取特征,而是采用最远距离采样,选取不同个个数的采样点,从细节到轮廓多层次采样,其次在进行卷积时,对于PointNet只在最后一层进行maxpooling来获得最终特征值,但是PF-Net则在提取的过程中,在卷积提取过程中,对卷积结果进行maxpooling提取特征,最终将多次maxpooling提取到的特征拼接,使特征既有轮廓信息,又有细节信息。

在这里插入图片描述

class Latentfeature(nn.Module):
    # ..
    def forward(self, x):
        outs = []  # 用于存储各层的输出结果
        print(x[0].shape)  # 打印输入数据第一个尺度的形状

        # 对第一个尺度的数据进行卷积处理,并将结果存入 outs 列表
        for i in range(self.each_scales_size):
            outs.append(self.Convlayers1[i](x[0]))

        # 对第二个尺度的数据进行卷积处理,并将结果存入 outs 列表
        for j in range(self.each_scales_size):
            outs.append(self.Convlayers2[j](x[1]))

        # 对第三个尺度的数据进行卷积处理,并将结果存入 outs 列表
        for k in range(self.each_scales_size):
            outs.append(self.Convlayers3[k](x[2]))

        # 将不同尺度的卷积输出在维度2上拼接起来,得到拼接后的特征
        latentfeature = torch.cat(outs, 2)

        # 将拼接后的特征进行转置操作,交换维度1和维度2
        latentfeature = latentfeature.transpose(1, 2)

        # 通过卷积层和批归一化层,对拼接特征进行卷积和激活处理
        latentfeature = F.relu(self.bn1(self.conv1(latentfeature)))

        # 压缩特征图的一个维度,将其从 (batch_size, 1, ...) 变为 (batch_size, ...)
        latentfeature = torch.squeeze(latentfeature, 1)

        return latentfeature  # 返回最终的特征图

# 来源 self.Convlayers1[i](x[0])
class Convlayer(nn.Module):
	# ..
    def forward(self, x):
        x = torch.unsqueeze(x, 1)  # 在输入的维度上增加一个维度,转换为 (batch_size, 1, point_num, 3)

        # 通过第一层卷积+批归一化+ReLU激活
        x = F.relu(self.bn1(self.conv1(x)))

        # 通过第二层卷积+批归一化+ReLU激活
        x = F.relu(self.bn2(self.conv2(x)))

        # 通过第三层卷积,提取128通道的特征
        x_128 = F.relu(self.bn3(self.conv3(x)))

        # 通过第四层卷积,提取256通道的特征
        x_256 = F.relu(self.bn4(self.conv4(x_128)))

        # 通过第五层卷积,提取512通道的特征
        x_512 = F.relu(self.bn5(self.conv5(x_256)))

        # 通过第六层卷积,提取1024通道的特征
        x_1024 = F.relu(self.bn6(self.conv6(x_512)))

        # 使用最大池化层对 x_128 进行池化,去除掉特征图的某一维度
        x_128 = torch.squeeze(self.maxpool(x_128), 2)

        # 对其他特征图 x_256, x_512, x_1024 同样进行池化操作
        x_256 = torch.squeeze(self.maxpool(x_256), 2)
        x_512 = torch.squeeze(self.maxpool(x_512), 2)
        x_1024 = torch.squeeze(self.maxpool(x_1024), 2)

        # 将各层的特征图按通道拼接
        L = [x_1024, x_512, x_256, x_128]
        x = torch.cat(L, 1)  # 将四层特征拼接在一起

        return x  # 返回最终特征

这样的过程会进行三次,对于不同采样点个数都进行处理

Point Pyramid Deconder(PPD)

解码器,在进行预测时,先是预测出一个轮廓,再将轮廓信息加入到下面,逐级预测更多的细节,慢慢加入特征,使预测更急准确。

在这里插入图片描述

class _netG(nn.Module):
    def forward(self, x):
        # 获取输入特征
        x = self.latentfeature(x)

        # 通过全连接层并激活处理,逐步缩小特征维度
        x_1 = F.relu(self.fc1(x))  # 1024维度的特征处理
        x_2 = F.relu(self.fc2(x_1))  # 512维度的特征处理
        x_3 = F.relu(self.fc3(x_2))  # 256维度的特征处理

        # 第一阶段输出特征并 reshape 成 64x3 的中心点特征
        pc1_feat = self.fc3_1(x_3)
        pc1_xyz = pc1_feat.reshape(-1, 64, 3)  # 中心点1,形状为64x3

        # 第二阶段输出特征,并 reshape 为 128x64 的特征
        pc2_feat = F.relu(self.fc2_1(x_2))
        pc2_feat = pc2_feat.reshape(-1, 128, 64)  # 中心点2的特征
        pc2_xyz = self.conv2_1(pc2_feat)  # 处理中心点2

        # 第三阶段输出特征,并经过多个卷积层处理,最终 reshape 为 512x128 的特征
        pc3_feat = F.relu(self.fc1_1(x_1))
        pc3_feat = pc3_feat.reshape(-1, 512, 128)
        pc3_feat = F.relu(self.conv1_1(pc3_feat))
        pc3_feat = F.relu(self.conv1_2(pc3_feat))
        pc3_xyz = self.conv1_3(pc3_feat)  # 细化点云的特征

        # 扩展 pc1_xyz 的维度以便与 pc2_xyz 相加
        pc1_xyz_expand = torch.unsqueeze(pc1_xyz, 2)

        # 转置并 reshape pc2_xyz,然后与扩展后的 pc1_xyz 相加
        pc2_xyz = pc2_xyz.transpose(1, 2)
        pc2_xyz = pc2_xyz.reshape(-1, 64, 2, 3)
        pc2_xyz = pc1_xyz_expand + pc2_xyz
        pc2_xyz = pc2_xyz.reshape(-1, 128, 3)  # 中心点2的坐标

        # 扩展 pc2_xyz 的维度以便与 pc3_xyz 相加
        pc2_xyz_expand = torch.unsqueeze(pc2_xyz, 2)

        # 转置并 reshape pc3_xyz,然后与扩展后的 pc2_xyz 相加
        pc3_xyz = pc3_xyz.transpose(1, 2)
        pc3_xyz = pc3_xyz.reshape(-1, 128, int(self.crop_point_num / 128), 3)
        pc3_xyz = pc2_xyz_expand + pc3_xyz
        pc3_xyz = pc3_xyz.reshape(-1, self.crop_point_num, 3)  # 细化后的点云坐标

        # 返回第一阶段、第二阶段和最终阶段的点云坐标
        return pc1_xyz, pc2_xyz, pc3_xyz  # 返回中心点1、中心点2和细化点

Discriminator

判別器,与GAN中的判别器逻辑一模一样,有两组输入,对比是否预测准确,实际上就是做了一个二分类,输出每个点结果为True或False,表示预测是否正确。

class _netlocalD(nn.Module)# ...
    def forward(self, x):
        # 输入经过第一个卷积层和批归一化后激活
        x = F.relu(self.bn1(self.conv1(x)))

        # 输入经过第二个卷积层和批归一化后激活,得到 64 维的特征
        x_64 = F.relu(self.bn2(self.conv2(x)))

        # 输入经过第三个卷积层和批归一化后激活,得到 128 维的特征
        x_128 = F.relu(self.bn3(self.conv3(x_64)))

        # 输入经过第四个卷积层和批归一化后激活,得到 256 维的特征
        x_256 = F.relu(self.bn4(self.conv4(x_128)))

        # 对 64 维特征进行最大池化并 squeeze 以减少维度
        x_64 = torch.squeeze(self.maxpool(x_64))

        # 对 128 维特征进行最大池化并 squeeze 以减少维度
        x_128 = torch.squeeze(self.maxpool(x_128))

        # 对 256 维特征进行最大池化并 squeeze 以减少维度
        x_256 = torch.squeeze(self.maxpool(x_256))

        # 将 64、128 和 256 维的特征拼接在一起
        Layers = [x_256, x_128, x_64]
        x = torch.cat(Layers, 1)

        # 全连接层逐层缩小特征维度并进行激活
        x = F.relu(self.bn_1(self.fc1(x)))
        x = F.relu(self.bn_2(self.fc2(x)))
        x = F.relu(self.bn_3(self.fc3(x)))

        # 最后一层全连接层输出结果
        x = self.fc4(x)

        return x

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

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

相关文章

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名…

【深度学习】LSTM模型,GRU模型计算公式及其优缺点介绍

一.LSTM介绍 LSTM(Long Short-Term Memory)也称长短时记忆结构, 它是传统RNN的变体, 与经典RNN相比能够有效捕捉长序列之间的语义关联, 缓解梯度消失或爆炸现象. 同时LSTM的结构更复杂, 它的核心结构可以分为四个部分去解析: 遗忘门输入门细胞状态输出…

基于SpringBoot的智能制造云平台系统的设计与实现计算机毕设

一、选题背景与意义(300字左右) 根据工业4.0智能制造生态链中云工厂在实际生产当中的工作流程进行充分调研和整理出来的,描述最终用户在本系统中对于生产订单的处理、排产、以及生产的完整在线处理流程和业务需求的文档。 针对制造业而言&a…

WebGL系列教程三(使用缓冲区绘制三角形)

目录 1 前言2 缓冲区介绍3 声明顶点的位置和颜色4 回忆Shader的初始化5 开始缓冲区的逻辑5.1 声明顶点坐标5.2 创建并绑定缓冲区5.3 获取顶点着色器中的变量5.4 使变量从缓冲区取值5.5 绘制5.6 完整代码 7 总结 1 前言 上一篇中我们介绍了WebGL的环境搭建及Shader的初始化&…

搭建Docker私有仓库管理本地的Docker镜像,通过harbor实现Web UI访问和管理私有仓库

要在本地搭建一个Docker私有仓库,你可以按照以下步骤进行设置: 安装Docker 确保你已经安装了Docker。如果还没有安装,可以按照官方指南进行安装: 对于Ubuntu系统,你可以运行以下命令来安装Docker: sudo ap…

区块链-P2P(八)

前言 P2P网络(Peer-to-Peer Network)是一种点对点的网络结构,它没有中心化的服务器或者管理者,所有节点都是平等的。在P2P网络中,每个节点都可以既是客户端也是服务端,这种网络结构的优点是去中心化、可扩展…

【JAVA入门】Day36 - 异常

【JAVA入门】Day36 - 异常 文章目录 【JAVA入门】Day36 - 异常一、异常结构体系综述1.1 错误(Error)1.2 异常(Exception)1.3 运行时异常(RuntimeException)1.4 其他异常 二、编译时异常和运行时异常三、异常…

WebDriver与Chrome DevTools Protocol:如何在浏览器自动化中提升效率

介绍 随着互联网数据的爆炸式增长,爬虫技术成为了获取信息的重要工具。在实际应用中,如何提升浏览器自动化的效率是开发者常常面临的挑战。Chrome DevTools Protocol(CDP)与Selenium WebDriver相结合,为浏览器自动化提…

vue中ES6的属性every使用@2@

every用于判断数组中的每一项是否均符合条件&#xff0c;并返回一个布尔值&#xff0c;都符合返回true&#xff0c;有一个不符合就返回false&#xff0c;并不再继续执行 //everyvar arr2 [1, 2, 3, 4, 5] let newArr2 arr2.every((num) > {return num < 3}) consol…

安卓13禁止声音调节对话框 删除音量调节对话框弹出 屏蔽音量对话框 android13

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析3.1 方法13.2 方法24.代码修改4.1 代码修改方法14.2 代码修改方法25.编译6.彩蛋1.前言 客户需要,调整声音,不显示声音调节对话框了。我们在系统里面隐藏这个对话框。 2.问题分析 android在调整声音的…

Chainlit集成Mem0使用一个拥有个性化AI记忆的网页聊天应用

前言 Mem0 简介&#xff0c;可以看我上一篇文章《解决LLM的永久记忆的解决方案-Mem0实现个性化AI永久记忆功能》。本篇文章是对Mem0 实战使用的一个示例。通过Chainlit 快速实现ui界面和open ai的接入&#xff0c;通过使用Mem0 实现对聊天者的对话记录的记忆。 设计实现基本原…

网络空间信息安全实验

实验1 基础实验&#xff08;加密与隐藏&#xff09; 一、实验目的 提高对加密与解密原理的认识&#xff1b;提高对信息隐藏原理的认识&#xff1b;学会使用加密与隐藏软件。 二、实验环境 Pentiuum III、600 MHz以上CPU , 128M 以上内存&#xff0c;10G 以上硬盘&#xff0…

Hoverfly api/v2/simulation 任意文件读取漏洞复现(CVE-2024-45388)

0x01 产品简介 Hoverfly是一个为开发人员和测试人员提供的轻量级服务虚拟化/API模拟/API模拟工具。 0x02 漏洞概述 Hoverfly api/v2/simulation 接口存在任意文件读取漏洞,未经身份验证攻击者可通过该漏洞读取系统重要文件(如数据库配置文件、系统配置文件)、数据库配置文…

CSS学习13--学成网例子

CSS例子 学成网 需要使用的图片&#xff1a; 代码&#xff1a; <html><head><style>/*CSS初始化*/* { /*清除内外边框*/padding: 0;margin: 0;}ul {list-style: none; /*清除列表样式*/}.clearfix:before,.clearfix:after { /*清除浮动*/content: &qu…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 9月9日,星期一

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年9月9日 星期一 农历八月初七 1、 三部门&#xff1a;拟允许在北京、天津、上海、广州、深圳、南京等地设立外商独资医院。 2、 巴黎残奥会结束&#xff1a;中国体育代表团获得94金76银50铜&#xff0c;连续六届残奥会位列…

C语言第二周课

目录 引言: 一、数据类型大小及分类 (1)计算机中常用存储单位 (2)整体介绍一下C语言的数据类型分类。 (3)下面是我们本节课要学的基本内容----常用的数据类型 二、 数据类型的数值范围 三、打印输出类型 数据类型打印示例: 引言: 我们常常在写C语言程序时&#xff0c;总…

用AI操作电脑:使用PyQt和Python结合AI生成代码的实用指南

​ 在github上有这样一个名字叫做open-interpreter的项目&#xff0c;收获了52k个Star。该项目通过自然语言来控制电脑&#xff0c;极大简化了使用电脑的难度&#xff0c;提高了工作效率。受该项目启发&#xff0c;我们可以做一个中文版桌面AI助手。 分步思考&#xff1a; 自…

算法工程师转行大模型:时代的选择or个人的选择

算法工程师的黄金时代&#xff1a;大模型转行之路 随着人工智能技术的飞速发展&#xff0c;尤其是深度学习领域的大规模预训练模型&#xff08;大模型&#xff09;的兴起&#xff0c;算法工程师们正面临前所未有的机遇与挑战。本文旨在探讨算法工程师如何顺利过渡到大模型领域…

基于Matlab的图像去雾系统(四种方法)关于图像去雾的基本算法代码的集合,方法包括局部直方图均衡法、全部直方图均衡法、暗通道先验法、Retinex增强。

基于Matlab的图像去雾系统&#xff08;四种方法&#xff09; 关于图像去雾的基本算法代码的集合&#xff0c;方法包括局部直方图均衡法、全部直方图均衡法、暗通道先验法、Retinex增强。 所有代码整合到App designer编写的GUI界面中&#xff0c;包括导入图片&#xff0c;保存处…

吴恩达发布企业AI转型手册,AI Transformation Playbook,对公司高管、正在创业的AIer是不错的指南。

AI 时代&#xff0c;人人都在创业。 今天看到一篇吴恩达发布的 AI 转型指南&#xff0c;原文《 AI Transformation Playbook——How to lead your company into the AI era》。 对公司高管、正在创业的 AIer 是个不错的指南。 这本人工智能转型手册借鉴了领导谷歌大脑团队和百…