wannyaky_F 2024-03-17 10:05 采纳率: 60%
浏览 34
已结题

关于open3D处理平面点云粗糙度问题

open3D采用最小二乘法计算平面点云粗糙度,这个基准平面为什么,离点云那么远,不应该是根据点云拟合出来的吗,这样计算出来粗糙度值就很大,请问如何修改?

import open3d as o3d
import matplotlib.pyplot as plt
from numpy import *
import numpy as np


def roughness_projection(point_list, plane_list):
    sa_list = []
    for i in range(len(plane_list)):
        A, B, C, D = plane_list[i]
        f_a, f_b, f_c, f_d = -A, -B, -C, -D

        x = point_list[i][:, 0]
        y = point_list[i][:, 1]
        z = point_list[i][:, 2]

        distance = []

        xp = []
        yp = []
        zp = []
        for j in range(len(x)):
            xp.append(
                ((f_b ** 2 + f_c ** 2) * x[j] - f_a * (f_b * y[j] + f_c * z[j] + f_d)) / (
                            f_a ** 2 + f_b ** 2 + f_c ** 2))
            yp.append(
                ((f_a ** 2 + f_c ** 2) * y[j] - f_b * (f_a * x[j] + f_c * z[j] + f_d)) / (
                            f_a ** 2 + f_b ** 2 + f_c ** 2))
            zp.append(
                ((f_a ** 2 + f_b ** 2) * z[j] - f_c * (f_a * x[j] + f_b * y[j] + f_d)) / (
                            f_a ** 2 + f_b ** 2 + f_c ** 2))
            distance.append(((x[j] - xp[j]) ** 2 + (y[j] - yp[j]) ** 2 + (z[j] - zp[j]) ** 2) ** (0.5))
        sa = mean(distance)
        sa_list.append(sa)
    return sa_list


def roughness_view(point_list, plane_list):
    fig1 = plt.figure()
    ax1 = fig1.add_subplot(111, projection='3d')
    ax1.set_xlabel("x")
    ax1.set_ylabel("y")
    ax1.set_zlabel("z")

    for i in range(len(plane_list)):
        x = point_list[i][:, 0]
        y = point_list[i][:, 1]
        z = point_list[i][:, 2]
        A, B, C, D = plane_list[i]
        a, b, c, d = A, B, -C, D

        ax1.scatter(x, y, z, color='gray', marker='.')

        x_p = np.linspace(min(x), max(x), 100)
        y_p = np.linspace(min(y), max(y), 100)
        x_p, y_p = np.meshgrid(x_p, y_p)
        z_p = a * x_p + b * y_p + d
        ax1.plot_wireframe(x_p, y_p, z_p, rstride=10, cstride=10)

    plt.show()
    return None


if __name__ == '__main__':
    # 拟合平面:z = 0.559 * x + 0.164 * y + -11.822
    plane_list = [[0.559, 0.164, -1, -11.822]]
    point_list = []
    pcd = o3d.io.read_point_cloud("2.pcd")
    pcd = np.asarray(pcd.points)
    point_list.append(pcd)

    sa_list = roughness_projection(point_list, plane_list)
    print("sa算术平均粗糙度:", sa_list)
    roughness_view(point_list, plane_list)
![img](https://img-mid.csdnimg.cn/release/static/image/mid/ask/824ca610cf4f4b0dbcb482363e239954.png "#left")


  • 写回答

6条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-03-17 10:05
    关注

    引自免费微信小程序:皆我百晓生

    在您的代码中,您首先从点云数据文件中读取点,并手动定义了一个平面方程(z = 0.559 * x + 0.164 * y - 11.822),然后计算了点云到这个给定平面的投影距离。然而,您发现基准平面与实际点云的距离较大,导致粗糙度值较高。

    要解决这个问题,您应该基于点云数据拟合一个平面,而不是直接使用预设的平面参数。Open3D库提供了一种通过RANSAC算法进行平面拟合的方法:

    import open3d as o3d
    
    # 读取点云数据
    pcd = o3d.io.read_point_cloud("2.pcd")
    
    # 使用RANSAC方法拟合平面
    plane_model, inliers = pcd.segment_plane(distance_threshold=0.01,
                                             ransac_n=3,
                                             num_iterations=1000)
    
    # 获取拟合平面的参数
    [A, B, C, D] = plane_model
    
    # 计算并输出粗糙度
    point_list = [np.asarray(pcd.points)]
    plane_list = [[A, B, -C, D]]  # 注意这里将C取负以适应您的函数格式
    sa_list = roughness_projection(point_list, plane_list)
    print("sa算术平均粗糙度:", sa_list)
    
    # 绘制结果
    roughness_view(point_list, plane_list)
    

    以上代码首先读取点云数据,然后利用segment_plane函数对点云进行平面拟合,获取到最佳平面参数后,再用这些参数去计算点云到该平面的粗糙度。这样得到的基准平面会更加贴近点云数据,从而得到更合理的粗糙度值。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(5条)

报告相同问题?

问题事件

  • 系统已结题 3月26日
  • 已采纳回答 3月18日
  • 创建了问题 3月17日