全流程点云机器学习(一)使用CloudCompare自制sharpNet数据集

前言

这不是高支模项目需要嘛,他们用传统算法切那个横杆竖杆流程复杂耗时很长,所以想能不能用机器学习完成这些工作,所以我就来整这个工作了。

工欲善其事,必先利其器,在正式开始之前,我们先要搞懂如何切分数据集。

本系列文章所用的核心骨干网络代码主要来自点云处理:实现PointNet点云分割

使用的数据集类型主要为SharpNet,这篇文章里主要是讲如何使用CC切出指定的对象,并将其转换成我们想要的SharpNet数据集。

之后可能写一个番外,简单说说如何使用semantic-segmentation-editor工具进行简单的点云分割和解析吧,最近也摸了一下,但是发现这个工具貌似没有CC好用。

如果有人问起再写吧,有点折腾,不过也还好。

什么是SharpNet数据集?

我们可以在 LARGE-SCALE 3D SHAPE RECONSTRUCTION AND SEGMENTATION
FROM SHAPENET CORE55网站上下载到SharpNet的数据集和标签,我们下载下来解压看看里面的结构
在这里插入图片描述
以下是训练集点云文件组
在这里插入图片描述
在这里插入图片描述

以下是训练集点云的标签组

也就是说实际上是一个pts文件对应一个.seg文件。

其中pts文件好理解,就是一个个的明文点云,内容如下:

在这里插入图片描述

打开seg文件,里面行数和同名的pts文件行数相同,

在这里插入图片描述

这个.seg文件中代表的意思就是对应行数的点所对应的label标签,通常以一个数字来表示,比如1是背景,2,3,4代表各种各样的对象,具体每个数字对应的对象是什么。

如何标注点云文件

上文中简单说了下SharpNet的规则,那么本章就简单说说如何标注点云文件

主要可以参考这篇文章,我这里仅展示简单的流程:

如何利用CloudCompare软件进行点云数据标注

比如我现在有一个这样的高支模点云,如果我想要做一个横杆的检测,那么我们就需要把横杆全部截出来

1.切割

在这里插入图片描述

先点击需要切片的点云文件,然后点这个剪刀进入剪切模式
在这里插入图片描述
先用左键划线工具框选住一个横杆,选完了之后单击右键确定选框,这个时候点击这个红色的多边形(选中框选内容)完成切割,再点击右边的这个绿色勾

在这里插入图片描述
在这里插入图片描述

这个时候切片就切出来了,可以看看效果

在这里插入图片描述

在这里插入图片描述

2. 分类

完成了切割工作之后,要给这个切出来的片加上一个名字,就点上面这个加号,然后给定一个对象的名称,再给定一个值

在这里插入图片描述
我们切分的是水平支撑,那么就给它起个名字叫Support

在这里插入图片描述

至于值的话随便声明就行,无所谓,这里声明的是1.00,这个和后面的处理有关,当然了你不懂也无所谓,如果你看懂了的话可以自己改这块的逻辑。

然后选中所有的点云,然后合并就行了
在这里插入图片描述
合并后可以看到被截取的这一块点云已经和原来的点云不一样了
在这里插入图片描述
在属性中找到Active可以找到被切分的点云分类

在这里插入图片描述
在这里插入图片描述
保存一下这个点云,保存成ASCII码的格式,以便我们对这个点云文件重新进行操作,以文本格式打开:
在这里插入图片描述
每个属性从上到下对应end_header后从左到右的一条条内容,比如第一行

7.099000 7.473000 4.869000 0 59 255 7.000000 1.000000 1.000000 0.000000

代表了一个点的
x坐标 y坐标 z坐标 r色 g色 b色 scalar_Intensity scalar_HSupport scalar_Support scalar_Original_cloud_index

我们在这里只需要判断Support的值就可以了,后面的几个scalar值就是标签的值,我们在这里只需要判断是不是Support对象,然后一行行地制作出.pts文件和.seg文件即可。

这里给出一段示例代码,需要注意的是,这个代码并不是自适应的识别所有标签,所以需要自己根据业务和自己的需要调整

CCSeperator.h

#pragma once#include <QtWidgets/QMainWindow>
#include "ui_CCSeperator.h"
#include "qpoint.h"
#include "qvector.h"
#include "qfile.h"
#include "qfileinfo.h"
#include "qtextstream.h"
#include "qdir.h"
#include "qdebug.h"
//CC数据清洗工具
enum class PointType {None = 0,Support = 1,VSupport = 2
};struct CCPoint {float x = 0.00;float y = 0.00;float z = 0.00;PointType type = PointType::None;
};class CCSeperator
{Q_OBJECTpublic:CCSeperator();~CCSeperator();/// <summary>/// 读取指定点云文件并尝试解析到指定目录下/// </summary>void ReadFile(const QString& filePath, const QString& outputPath);QVector<CCPoint> vec_points;
};

CCSeperator.cpp

#include "CCSeperator.h"CCSeperator::CCSeperator()
{this->ReadFile("J:\\output\\GF3_7.ply", "J:\\output");
}CCSeperator::~CCSeperator()
{}void CCSeperator::ReadFile(const QString& filePath, const QString& outputPath)
{//尝试读取指定目录下的文件QFile file(filePath);QString fileName = QFileInfo(file).baseName();if (!file.exists()) {qDebug() << " file not exist";return;}this->vec_points.clear();qDebug() << file.open(QIODevice::ReadWrite | QIODevice::Text);QTextStream in(&file);bool blnEndHead = false;while (!in.atEnd()) {QString line = in.readLine();if (line.contains("end_header")) {blnEndHead = true;continue;}if (!blnEndHead) continue;QStringList list = line.split(" ");CCPoint point;point.x = list[0].toFloat();point.y = list[1].toFloat();point.z = list[2].toFloat();//这个对应的是识别的列,这里是第七行if (list[6].toFloat() == 1.0000) {point.type = PointType::Support;}else {point.type = PointType::None;}this->vec_points.append(point);}//注入点完成后,需要将其导出到指定目录下QDir dir(outputPath);if (!dir.exists()) {dir.mkpath(dir.absolutePath());}QFile file_out_data(outputPath + QString("/Data/%1.pts").arg(fileName));QTextStream out(&file_out_data);QFile file_out_label(outputPath + QString("/Label/%1.seg").arg(fileName));QTextStream out_label(&file_out_label);file_out_data.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);file_out_label.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);for (auto item : this->vec_points) {//将所有的点写入到指定目录下//无论如何,正常的点都需要写入QString fileContent = QString("%1 %2 %3").arg(item.x).arg(item.y).arg(item.z);out << fileContent << endl;QString label = QString("%1").arg(static_cast<qint32>(item.type));out_label << label << endl;}file_out_data.close();file_out_label.close();
}

这样洗出来的数据就是这样的:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这样我们就完成了自制SharpNet数据集的过程

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

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

相关文章

API接口实现自动化数据同步

一、API的核心作用 API是现代电子商务生态系统中不可或缺的组成部分&#xff0c;它使得不同平台和服务之间的数据共享变得可能。通过API&#xff0c;开发者可以访问到商品信息、用户评价、销售数据等&#xff0c;这些数据对于市场分析、库存管理和用户体验优化至关重要。 二、…

每日leetcode--删除有序数组中的重复项

问题描述 给定一个包含重复元素的整数列表nums&#xff0c;我们需要移除其中的重复元素&#xff0c;并返回去重后的列表长度。 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 解决方案&#xff1a; 我们可以使用一个额外的列表来存储不重复的元素&#xff…

Linux 开启防火墙 --- FirewallD is not running 问题修复

问题 在配置SSL认证后&#xff0c;需要放开防火墙的443端口&#xff0c;出现了FirewallD is not running错误 [rootxxx ~]# firewall-cmd --zonepublic --add-port443/tcp --permanent FirewallD is not running解决 只需要开启防火墙即可。 【1】先通过systemctl status fir…

旅游分享系列之:福建旅游攻略

旅游分享系列之&#xff1a;福建旅游攻略 一、漳州1.福建土楼2.云水谣3.四菜一汤景点 二、厦门1.园林博览苑2.海上自行车道3.山海步道4.海滩5.闽南菜6.落日 三、泉州1.衙口沙滩2.海上日出3.珞珈寺4.海滩烟花 一、漳州 游玩2个景点&#xff1a;云水谣&#xff0c;四菜一汤可以住…

基于Java+SpringBoot+Vue前后端分离仓库管理系统设计实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

QT常用类

五、常用类 QString 字符串类&#xff08;掌握&#xff09; QString是Qt的字符串类&#xff0c;与C的std::string相比&#xff0c; 不再使用ASCII编码。QString使用的是Unicode编码。 QString中每个字符都是一个16位的QChar&#xff0c;而不是8位的char。 QString完全支持中文&…

深入探究node搭建socket服务器

自从上篇中sokect实现了视频通话&#xff0c;但是是使用ws依赖库实现的服务端&#xff0c;所以最近再看ws源码&#xff0c;不看不知道&#xff0c;一看很惊讶。 接下来一点点记录一下&#xff0c;如何搭建一个简易的服务端socket&#xff0c;来实现上次的视频通讯。 搭建一个…

详解AP3216C(三合一sensor: 光照、距离、照射强度)驱动开发

目录 概述 1 认识AP3216C 1.1 AP3216C特性 1.2 AP3216C内部结构 1.3 AP3216C 硬件电路 1.4 AP3216C工作时序 1.4.1 I2C 写数据协议 1.4.2 I2C 读数据协议 1.5 重要的寄存器 1.5.1 系统配置寄存器 1.5.2 和中断相关寄存器 1.5.3 IR数据寄存器 1.5.4 ALS 数据寄存器 …

十二、线性代数二-二次型:

目录 1、二次型的定义: 2、二次矩阵与二次型的理解: 3、二次型矩阵的性质: 4、二次型的标准型: 5、二次型的正定型: ①正定型的概念: ②二次型正定型的判定:

代码随想录算法训练营第59天 | 583.两个字符串的删除操作 + 72.编辑距离 + 编辑距离总结篇

今日任务 583. 两个字符串的删除操作 72. 编辑距离 编辑距离总结篇 583.两个字符串的删除操作 - Medium 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 相同所需的最小步数。 每步 可以…

tombstone常见崩溃信号说明

一、概念说明 在应用崩溃的时候&#xff0c;我们将会获取到两个信息: signal: 信号量&#xff0c;下文将会详细的说明不同的信号量及其含义。code: 错误码, 除了几个所有信号量(signal) 公共的错误码(code)&#xff0c;一般不同信号量(signal)有特定的错误码(code)&#xff0c;…

LeetCode题练习与总结:三数之和

一、题目 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。 请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组…

【数学建模规则】2024年第九届数维杯大学生数学建模挑战赛参赛指南

一、竞赛介绍 数维杯大学生数学建模挑战赛每年分为两场&#xff0c;每年上半年为数维杯国赛&#xff08;5月&#xff0c;俗称小国赛&#xff09;&#xff0c;下半年为数维杯国际赛(11月)&#xff0c;2023年第八届数维杯大学生数学建模挑战赛共有近1.4万名学生参赛&#xff0c;…

Unity之PUN2插件实现多人联机射击游戏

目录 &#x1f4d6;一、准备工作 &#x1f4fa;二、UI界面处理 &#x1f4f1;2.1 登录UI并连接PUN2服务器 &#x1f4f1;2.2 游戏大厅界面UI &#x1f4f1;2.3 创建房间UI &#x1f4f1;2.4 进入房间UI &#x1f4f1;2.5 玩家准备状态 &#x1f4f1;2.6 加载战斗场景…

vue proxy解决跨域问题

https://blog.csdn.net/tttttrrrhh/article/details/127685318 cims系统ui

java 面向对象-上:类的结构之二

类的设计中&#xff0c;两个重要结构之二&#xff1a;方法 方法 描述类应该具的功能。 比如&#xff1a;Math类&#xff1a;sqrt()\random() \... Scanner类&#xff1a;nextXxx() ... Arrays类&#xff1a;sort() \ binarySearch() \ toString() \ equals() \ ... 1.举例 p…

【nginx作为缓存服务器】

目录 一、Nginx缓存介绍二、Nginx配置缓存1.缓存开关:proxy_cache2.代理缓存:proxy_cache_path4.缓存过期 一、Nginx缓存介绍 Nginx可以对浏览器缓存进行配置&#xff0c;让一些静态资源缓存到用户本地存储&#xff0c;以提高页面的响应速度&#xff0c;也能降低服务端的压力&…

c入门第二十一篇: 学生成绩管理系统之成绩排序

前言 在学生成绩管理系统中&#xff0c;必然面临着排序的问题。这里我们简单的将之前讲过的冒泡排序应用于我们的学生成绩管理系统中。 冒泡排序是一种简单的排序算法&#xff0c;它重复地遍历要排序的列表&#xff0c;比较相邻的两个项&#xff0c;如果相邻不是预期的顺序时交…

[Java 项目亮点] 三层限流设计

思路来源&#xff1a;bilibili 河北王校长 文章目录 面试官可能会问你能详细介绍一下Nginx的http_limit_req_module模块吗&#xff1f;你能解释一下如何在Nginx中配置http_limit_req_module模块吗&#xff1f;你知道如何调整Nginx的http_limit_req_module模块以适应不同的业务需…

【服务器数据恢复】通过reed-solomon算法恢复raid6数据的案例

服务器数据恢复环境&#xff1a; 一台网站服务器中有一组由6块磁盘组建的RAID6磁盘阵列&#xff0c;操作系统层面运行MySQL数据库和存放一些其他类型文件。 服务器故障&#xff1a; 该服务器在工作过程中&#xff0c;raid6磁盘阵列中有两块磁盘先后离线&#xff0c;不知道是管理…