当前位置: 首页 > news >正文

【最详解】如何进行点云的凹凸缺陷检测(opene3D)(完成度80%)

文章目录

  • 前言
  • 实现思路
    • 想法1
    • 想法2
    • 想法3
  • 补充
  • 实现
    • 想法1
    • 想法2
      • 代码
    • 想法3
      • 代码
  • 总结


前言

读前须知
首先我们得确保你已经完全知晓相关的基本的数学知识,其中包括用最小二乘法拟合曲二次曲面,以及曲面的曲率详细求解。若还是没弄清楚,则详细请看下面链接。

【点云、图像】学习中 常见的数学知识及其中的关系与python实战[更新中](建议从一个标题上从上往下看,比较循序渐进)

补充:曲率:反映曲面在某一点处的弯曲程度,它与该点及其邻近点的位置和法向量有关。

以及一些open3d的常见操作:
爆肝5万字❤️Open3D 点云数据处理基础(Python版)

先上结果:
在这里插入图片描述


实现思路

不同于常见的缺陷检测,如:划痕或者斑点这些肉眼可见的缺陷,凹凸性缺陷难以肉眼可见甚至得打光照射才能看见凹槽,这里我们使用深度摄像机(普通相机+深度信息),来采集深度信息。此时我们把图像称为深度图,当然深度图也可以转换为点云。

这里我们仅对点云这种数据进行处理。

要求:对异形曲面微细缺陷识别(我6月份之前要完成的毕设)
这里缺陷主要指凸起和凹槽。

想法1

想法1:如果是一个平面上出现凹槽或凸起的话,首先确立一个由大部分点拟合的平面,然后对不在此平面的点云进行高程分析,以确立凹陷或凸起程度。
(事实上不会很平,于是想法1排除,但可以用来做平面来做一个简单示例)

想法2

想法2:计算点云上每个点的领域曲率来描绘点的弯曲程度。

想法3

想法3:计算点云上每个点的高斯曲率和平均曲率来描绘点的弯曲程度。

补充

机器学习——详解KD-Tree原理

实现

想法1

暂无

想法2

想法2:
在求取完领域曲率的基础上,我们对其曲率的大小进行一个分割,并进行可视化。

这里进一步对这个领域曲率的定义进行详解。
首先,我们已经在这里的实战1了解到了领域曲率的求法。
在这里插入图片描述

基于邻域特征点提取和匹配的点云配准_李新春

可是这个定义我只在其他的博客中和下面这篇论文中找到定义,并无在wiki百科中找到相关阐述。

找了半天后依然无法解释其中原因,于是在参考了下面两篇博文后
如何理解矩阵特征值?
特征值的最大值与最小值
想出了这么一个合理的解释:
1、这个曲率定义的优点是,它不依赖于法向量的方向,而且它的值域是 [0, 1/3],这使得它比较容易进行归一化和可视化。

2、那么,为什么用最小的特征值除以特征值和,而不是用最大的特征值除以特征值和呢?

这是因为最小的特征值对应的特征向量是曲面的法向量,而最大的特征值对应的特征向量是曲面的主方向。

如果用最大的特征值除以特征值和,那么曲率的值就会与曲面的主方向的弯曲程度成正比,而与曲面的法向方向的弯曲程度无关。这样就会忽略掉曲面的凹凸变化,导致曲率的计算不准确。

如果用最小的特征值除以特征值和,那么曲率的值就会与曲面的法向方向的弯曲程度成正比,而与曲面的主方向的弯曲程度无关。这样就可以反映出曲面的凹凸变化,提高曲率的计算精度。

因此,用最小的特征值除以特征值和,而不是用最大的特征值除以特征值和,是为了更好地描述曲面的局部形状,而不是曲面的整体方向。

于是我们就可以坦然用这个定义来求取了。

代码

怕点云太多算不过来,首先对例子中的兔子点云进行了一个下采样。(如何获取兔子点云到时候再出教程)

import open3d as o3d
import numpy as npdef pca_compute(data, sort=True): #1、主成分分析average_data = np.mean(data, axis=0) # 求每一列的平均值,即求各个特征的平均值decentration_matrix = data - average_data  # 去中心化矩阵H = np.dot(decentration_matrix.T, decentration_matrix)  # 求协方差矩阵 #协方差是衡量两个变量关系的统计量,协方差为正表示两个变量正相关,为负表示两个变量负相关eigenvectors, eigenvalues, eigenvectors_T = np.linalg.svd(H) # 求特征值与特征向量 #H = UΣV^T #输出列向量、对角矩阵、行向量if sort:sort = eigenvalues.argsort()[::-1] # 从大到小排序 .argsort()是升序排序,[::-1]是将数组反转,实现降序排序eigenvalues = eigenvalues[sort] # 特征值  ## 使用索引来获取排序后的数组return eigenvaluesdef caculate_surface_curvature(radius,pcd):#2、计算点云的表面曲率cloud = pcdpoints = np.asarray(cloud.points) #点云转换为数组 点云数组形式为[[x1,y1,z1],[x2,y2,z2],...]kdtree = o3d.geometry.KDTreeFlann(cloud) #建立KDTreenum_points = len(cloud.points) #点云中点的个数curvature = []  # 储存表面曲率for i in range(num_points):k, idx, _ = kdtree.search_radius_vector_3d(cloud.points[i], radius) #返回邻域点的个数和索引neighbors = points[idx] #数组形式为[[x1,y1,z1],[x2,y2,z2],...]w = pca_compute(neighbors)#调用第1步  #由降序排序,w[2]为最小特征值  #np.zeros_like(w[2])生成与w[2]相同形状的全0数组delt = np.divide(w[2], np.sum(w)) #根据公式求取领域曲率curvature.append(delt)curvature = np.array(curvature, dtype=np.float64)return curvaturedef curvature_normal():#3、曲率归一化 从0-1/3归到0-1之间curvature = caculate_surface_curvature(radius,pcd) #调用第2步c_max = max(curvature)c_min = min(curvature)cur_normal = [(float(i) - c_min) / (c_max - c_min) for i in curvature] return cur_normaldef draw(cur_max,cur_min,pcd):#4、绘图cur_normal = curvature_normal()#调用第3步pcd.paint_uniform_color([0.5,0.5,0.5]) #初始化所有颜色为灰色for i in range(len(cur_normal)):if 0 < cur_normal[i] <= cur_min: #归一化后的曲率np.asarray(pcd.colors)[i] = [1, 0, 0]#红elif cur_min < cur_normal[i] <= cur_max:np.asarray(pcd.colors)[i] = [0, 1, 0]#绿elif cur_max < cur_normal[i] <= 1: np.asarray(pcd.colors)[i] = [0, 0, 1]#蓝# 可视化o3d.visualization.draw_geometries([pcd])cur_max = 0.7 
cur_min = 0.3 #曲率分割基准
radius = 0.05
voxel_size = 0.01 #越小密度越大
pcd = o3d.io.read_point_cloud("bunny.pcd")
print(pcd)
pcd = pcd.voxel_down_sample(voxel_size) #下采样
draw(cur_max,cur_min,pcd)

结果:
在这里插入图片描述
这个长度,宽度报错可以不管,有点子强迫症的可以在可视化改成:

    o3d.visualization.draw_geometries([pcd],window_name="可视化原始点云",width=800, height=800, left=50, top=50,mesh_show_back_face=False)

在这里插入图片描述
红色为曲率较低,绿色曲率中等,蓝色曲率较高。
发现效果上不太行,红色一些部分看着曲率也很高,甚至还出现了一个初始化时候的灰点,可能求邻近点的时候没取到?不曾得知。

想法3

首先我们在这里的高斯曲率和平均曲率求解有了一些认识。
附一张图:
在这里插入图片描述

代码

import open3d as o3d
import numpy as np
from scipy.optimize import curve_fitvoxel_size = 0.01 #越小密度越大
radius = 0.07
pcd = o3d.io.read_point_cloud("bunny.pcd")
pcd = pcd.voxel_down_sample(voxel_size) #下采样
cloud = pcd
points = np.asarray(cloud.points) #点云转换为数组 点云数组形式为[[x1,y1,z1],[x2,y2,z2],...]
kdtree = o3d.geometry.KDTreeFlann(cloud) #建立KDTree
num_points = len(cloud.points) #点云中点的个数
pcd.paint_uniform_color([1, 0, 0])  # 初始化所有颜色为红色
# 定义非线性函数,这里假设是一个二次曲面
def func(x, a, b, c, d, e, f):return a * x[0]**2 + b * x[1]**2 + c * x[0] * x[1] + d * x[0] + e * x[1] + f
def f(x, y):return popt[0]*x**2 +popt[1]*y**2 +popt[2]* x*y +popt[3]*x + popt[4]*y +popt[5]
# 定义曲面的梯度函数,即一阶偏导数
def gradient(f, x, y):# 使用中心差分法近似求导  #参考https://cloud.tencent.com/developer/article/1685164h = 1e-6 # 差分步长,可以根据精度要求调整df_dx = (f(x + h, y) - f(x - h, y)) / (2 * h) # 对x求偏导df_dy = (f(x, y + h) - f(x, y - h)) / (2 * h) # 对y求偏导return df_dx, df_dy
# 定义曲面的曲率函数,即二阶偏导数
def curvature(f, x, y):# 使用中心差分法近似求导h = 1e-6 # 差分步长,可以根据精度要求调整d2f_dx2 = (f(x + h, y) - 2 * f(x, y) + f(x - h, y)) / (h ** 2) # 对x求二阶偏导d2f_dy2 = (f(x, y + h) - 2 * f(x, y) + f(x, y - h)) / (h ** 2) # 对y求二阶偏导d2f_dxdy = (f(x + h, y + h) - f(x + h, y - h) - f(x - h, y + h) + f(x - h, y - h)) / (4 * h ** 2) # 对xy求混合偏导# 根据公式计算高斯曲率K和平均曲率Hdf_dx, df_dy = gradient(f, x, y) # 调用梯度函数求一阶偏导E = 1 + df_dx ** 2F = df_dx * df_dyG = 1 + df_dy ** 2L = d2f_dx2 / np.sqrt(1 + df_dx ** 2 + df_dy ** 2) #np.sqrt()表示开方M = d2f_dxdy / np.sqrt(1 + df_dx ** 2 + df_dy ** 2)N = d2f_dy2 / np.sqrt(1 + df_dx ** 2 + df_dy ** 2)K = (L * N - M ** 2) / (E * G - F ** 2) # 高斯曲率H = (E * N + G * L - 2 * F * M) / (2 * (E * G - F ** 2)) # 平均曲率return K, Hcurvatures = []  
for i in range(num_points):k, idx, _ = kdtree.search_radius_vector_3d(cloud.points[i], radius) #返回邻域点的个数和索引neighbors = points[idx] #数组形式为[[x1,y1,z1],[x2,y2,z2],...]#print(k)Y = neighbors[:, 2] # 因变量X = neighbors[:, [0,1]] # 自变量 [[2,3],[1,1],[8,9],[11,12],[4,5],[8,9]] 6*2popt, pcov = curve_fit(func, xdata=X.T,ydata= Y)x = cloud.points[i][0] # 某一点的x坐标y = cloud.points[i][1] # 某一点的y坐标K, H = curvature(f, x, y) # 计算该点的曲率curvatures.append([K,H])print(curvatures)
for i in range(len(curvatures)):if -0.05<curvatures[i][0] < 0.05 and -0.05<curvatures[i][1] <0.05: #平坦np.asarray(pcd.colors)[i] = [0, 0, 0]#黑elif -0.05<curvatures[i][0] < 0.05 and curvatures[i][1] >0.05:  #凸np.asarray(pcd.colors)[i] = [1, 0, 0]#红elif -0.05<curvatures[i][0] < 0.05 and -0.05<curvatures[i][1] <0.05: #凹np.asarray(pcd.colors)[i] = [0, 1, 0]#绿elif curvatures[i][0] < -0.05 and curvatures[i][1] >0.05: #鞍形脊 大部分凸,少部分凹np.asarray(pcd.colors)[i] = [0, 0, 1]#蓝elif curvatures[i][0] < -0.05 and curvatures[i][1] <-0.05: #鞍形谷 大部分凹,少部分凸np.asarray(pcd.colors)[i] = [0, 1, 1]#青elif curvatures[i][0] > 0.05 and curvatures[i][1] >0.05: #峰 np.asarray(pcd.colors)[i] = [1, 0, 1]#紫elif curvatures[i][0] > 0.05 and curvatures[i][1] <-0.05: #阱np.asarray(pcd.colors)[i] = [1, 1, 0]#黄#显示点云
o3d.visualization.draw_geometries([pcd])

结果:
在这里插入图片描述
结果出奇的好,每个点都进行了划分,比想法1好太多了。这里暂时用兔子点云测试,到时候创造一些平面点云再来测试一下。


总结

学习东西都不是一蹴而就的,果然还是得一步一步脚踏实地地学才学的明白。chatgpt是个好东西,只有你也会点东西时,它才会回答的正确,不能轻信之。

未完成:
ps:1、兔子点云pcd读取
2、创建平面点云
3、返回面积、深度信息

相关文章:

【最详解】如何进行点云的凹凸缺陷检测(opene3D)(完成度80%)

文章目录 前言实现思路想法1想法2想法3 补充实现想法1想法2代码 想法3代码 总结 前言 读前须知&#xff1a; 首先我们得确保你已经完全知晓相关的基本的数学知识&#xff0c;其中包括用最小二乘法拟合曲二次曲面&#xff0c;以及曲面的曲率详细求解。若还是没弄清楚&#xff0…...

海外云手机——平台引流的重要媒介

随着互联网的飞速发展&#xff0c;跨境电商、短视频引流以及游戏行业等领域正经历着迅猛的更新换代。在这个信息爆炸的时代&#xff0c;流量成为至关重要的资源&#xff0c;而其中引流环节更是关乎业务成功的关键。海外云手机崭露头角&#xff0c;成为这一传播过程中的重要媒介…...

数据库-计算机三级学习记录-4DBAS功能概要设计

DBAS功能概要设计 参照b站【计算机三级数据库技术】 DBAS功能设计包括应用软件中的数据库事务设计和应用程序设计。 功能设计过程一般被划分为总体设计、概要设计和详细设计。而具体到数据库事务设计部分&#xff0c;又可分成事务概要设计和事务详细设计。完成系统设计工作之后…...

JVM-虚拟机栈

虚拟机栈 Java虚拟机栈&#xff08;Java Virtual Machine Stack&#xff09;采用栈的数据结构来管理方法调用中的基本数据&#xff0c;先进后出&#xff08;First In Last Out&#xff09;,每一个方法的调用使用一个栈帧&#xff08;Stack Frame&#xff09;来保存。 接下来以…...

linux系统上tomcat简介以及安装tomcat

tomcat简介以及安装 Tomcat简介安装环境安装jdk安装tomcat浏览器访问 Tomcat简介 Tomcat是一个开源的Web服务器和servlet容器&#xff0c;由Apache软件基金会开发和维护。它是一种流行的Java Web应用服务器&#xff0c;用于运行Java编写的Web应用程序。 Tomcat提供了一个轻量级…...

树莓派的pip安装时候添加清华源

每次都要去找镜像网址&#xff0c;太麻烦了&#xff0c;通过改配置可以一次性解决。 首先创建一个.pip 目录 mkdir ~/.pip意味着在当前目录下创建.pip文件&#xff0c;不过这个是隐藏文件&#xff0c;一般情况下是关闭隐藏文件的可视的&#xff0c;于是我绕了点弯弯。 编辑…...

共享网盘系统PHP源码

新V5.0版本&#xff0c;支持上传视频、支持视频播放、支持共享&#xff0c;也可以自己用。 可以自动生成视频外链&#xff0c;下载地址&#xff0c;播放器代码&#xff0c;html代码&#xff0c;ubb代码等等。 使用方法&#xff1a; 源码上传到服务器&#xff0c;打开网站根据…...

unity-ios-解决内购商品在Appstore上面已配置,但在手机测试时却无法显示的问题

自己这几天用 unity 2021 xcode 14.2 开发ios内购&#xff0c;appstore上面内购商品都已经配置好了&#xff0c;但是在手机里就是不显示&#xff0c;最后才发现必需得满足以下条件才行&#xff1a; 1. Appstore后台 -> 内购商品 -> 商品状态必需为『准备提交』以上状态…...

flask的基本使用 token插件(二)

一、安装flask-jwt-extended 安装flask-jwt-extend得时候 会自动安装一个pyjwt得库。pyjwt可以直接使用来生成JWT和验证。但是在flask中&#xff0c;可以通过Flask-JWT-Extended来实现JWT能&#xff0c;因为他封装了使用方式&#xff0c;以及一些属性和装饰器&#xff0c;用起…...

云计算、Docker、K8S问题

1 云计算 云计算作为一种新兴技术&#xff0c;已经在现代社会中得到了广泛应用。它以其高效、灵活和可扩展特性&#xff0c;成为了许多企业和组织在数据处理和存储方面的首选方案。 1.1 什么是云计算&#xff1f;它有哪些特点&#xff1f; 云计算是一种通过网络提供计算资源…...

【Iceberg学习二】Branch和Tag在Iceberg中的应用

Iceberg 表元数据保持一个快照日志&#xff0c;记录了对表所做的更改。快照在 Iceberg 中至关重要&#xff0c;因为它们是读者隔离和时间旅行查询的基础。为了控制元数据大小和存储成本&#xff0c;Iceberg 提供了快照生命周期管理程序&#xff0c;如 expire_snapshots&#xf…...

在 Blazor WASM 中手撸一个.NET MD5类

最近.net8 blazor auto大火, 我也玩了一下,发现ssr能用的代码 MD5 类在wasm是没法用的. 于是搜索了一下互联网,找到了一份代码,分享给大家. 我找到的帖子作者原话: 代码不是我的&#xff0c;但我确实稍微修改了它以使其与 System.Security.Cryptography.MD5 类更加一致。 pub…...

MFC实现遍历系统进程

今天我们来枚举系统中的进程和结束系统中进程。 认识几个API 1&#xff09;CreateToolhelp32Snapshot 用于创建系统快照 HANDLE WINAPI CreateToolhelp32Snapshot( __in DWORD dwFlags, //指定快照中包含的系统内容__in DWORD th32P…...

【C语言】深入理解指针

目录 1.字符指针 2.指针数组 3.数组指针 4.数组传参与指针传参 一维数组传参 二维数组传参 一级指针传参 二级指针传参 5.函数指针 6.函数指针数组 7.指向函数指针数组的指针&#xff08;了解即可&#xff09; 8.回调函数 回调函数的应用&#xff1a;库函数qsort …...

Excel——有效性、二级菜单联动

一、录入规范数据 1.手动输入序列录入有效性信息 选择需要录入有效性的所有单元格 选择【数据】——【有效性】——【有效性】 在【允许】输入的值之间选择【序列】 在【序列】输入框中输入想要选择的值&#xff0c;中间用逗号&#xff08;必须是英文逗号&#xff09;隔开 。…...

计算机网络总结

1. 网络分层 网络上进行协议分层的好处 ①分层之后层次之间的耦合程度比较低&#xff0c;上层协议不必了解下层的细节&#xff0c;下层也不必了解上层的细节&#xff1b; ②方便的对某一层的协议进行替换&#xff1b; 真实网络的协议分层 OSI 七层网络模型&#xff08;教科书&…...

初识文件包含漏洞

目录 什么是文件包含漏洞&#xff1f; 文件包含的环境要求 常见的文件包含函数 PHP伪协议 file://协议 php://协议 php://filter php://input zip://、bzip2://、zlib://协议 zip:// bzip2:// zlib:// data://协议 文件包含漏洞演示 案例1&#xff1a;php://inp…...

AR特效自研AI算法技术解决方案

在当今这个高速发展的数字化时代&#xff0c;增强现实&#xff08;AR&#xff09;技术已经成为企业创新和市场竞争的重要手段。美摄科技凭借对AI技术的深厚积累&#xff0c;为企业提供了一套创新的AR特效自研AI算法技术解决方案&#xff0c;旨在满足企业在AR领域的多元化需求。…...

牛客2024年除夕娱乐赛(题解)

比赛地址 : 牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A 看题面然后猜!!! #include<bits/stdc.h> using namespace std; int main(){cout << "原神启动" << endl; } B 也是看题面然后猜 : #include<bits/stdc.…...

5 scala的函数式编程简介

与Java一样&#xff0c;Scala 也是使用 Lambda 表达式实现函数式变成的。 1 遍历 除了使用 for 可以对数组、List、Set 进行遍历外&#xff0c;也可以使用 foreach 函数式编程进行遍历&#xff0c;使代码更为简洁。 foreach 的方法签名为&#xff1a; foreach(f: (A) > …...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...