点云处理PCL常用python函数与工具(二)

本文主要记录pcl点云处理常用工具,在此将每种方法写为一个函数,便于使用的时候直接调用。


本文主要记录pcl点云处理常用工具,在此将每种方法写为一个函数,便于使用的时候直接调用。

点云读取

提取指定范围内的点云数据(ROI点云提取),再将提取的数据转为pcl格式的点云。

from pclpy import pcl as pl
def LoadPointCloud(path,start, end):
    points = pl.PointCloud.PointXYZRGB()
    pl.io.load(path,points)
    data = np.zeros((points.size(),3),dtype=np.float32)
    data[:, 0] = points.x
    data[:, 1] = points.y
    data[:, 2] = points.z
    print("-------ROI data:{},{}".format(start, end))
    print("X max:{} X min:{} Y max:{} Y min:{}".format(np.max(data[:, 0]),np.min(data[:, 0]),np.max(data[:, 1]),np.min(data[:, 1])))
    data = data[(data[:, 0] > start[0])]
    data = data[(data[:, 0] < end[0])]
    data = data[(data[:, 1] < end[1])]
    data = data[(data[:, 1] > start[1])]
    points_region = pl.PointCloud.PointXYZ(data.reshape(-1,3))

点云显示

1、使用pl.visualization.PCLVisualizer进行点云显示

def PointCouldViewXYZ(points):
    # 显示点云
    viewer = pl.visualization.PCLVisualizer("CloudPoints")
    # 根据Z轴显示点云颜色
    fildColor = pl.visualization.PointCloudColorHandlerGenericField.PointXYZ(points, "z")
    viewer.addPointCloud(points,fildColor,"sample cloud")
    viewer.setBackgroundColor(0., 0., 0.)
    while (not viewer.wasStopped()):
        viewer.spinOnce(10)

在这里插入图片描述

点云法线计算

def compute_normal(cloud,ksearch=18,radius=0.7):
    # 计算点云法向量
    KdTree = pl.search.KdTree.PointXYZ()
    normals = pl.PointCloud.Normal()
    normal_estimator = pl.features.NormalEstimationOMP.PointXYZ_Normal()
    normal_estimator.setSearchMethod(KdTree)
    # normal_estimator.setRadiusSearch(radius)
    normal_estimator.setInputCloud(cloud)
    normal_estimator.setKSearch(ksearch)
    normal_estimator.compute(normals)
    return normals

根据索引提取点云

def getClusterPointsFromIndices(cloud,indices):
    child_cloud = pl.PointCloud.PointXYZ()  # 根据索引批量提取点
    extract = pl.filters.ExtractIndices.PointXYZ()
    extract.setInputCloud(cloud)
    pi = pl.vectors.Int(indices.indices)
    extract.setNegative(False)  # 如果设为true,可以提取指定index之外的点云
    extract.setIndices(pi)
    extract.filter(child_cloud)
    return child_cloud

点云统计滤波

def points_filter(points):
    sor = pl.filters.StatisticalOutlierRemoval.PointXYZ()
    cloud = pl.PointCloud.PointXYZ()
    sor.setInputCloud(points)
    sor.setMeanK(10)
    sor.setStddevMulThresh(10)
    sor.filter(cloud)

点云区域分割

def ChildRegionGrow(cloud,MinS=30,KSearch=30,n_neighbours=30,
                       smooth_threshold=5,curvature_threshold=0.1,residual_threshold = 0.3):
    tree = pl.search.KdTree.PointXYZ()
    tree.setInputCloud(cloud)
    normals = pl.PointCloud.Normal()
    ne = pl.features.NormalEstimationOMP.PointXYZ_Normal()
    ne.setInputCloud(cloud)
    ne.setSearchMethod(tree)
    # ne.setRadiusSearch(0.7)
    ne.setKSearch(KSearch)
    ne.compute(normals)

    rg = pl.segmentation.RegionGrowing.PointXYZ_Normal()
    rg.setInputCloud(cloud)
    rg.setInputNormals(normals)
    rg.setSearchMethod(tree)
    rg.setMinClusterSize(MinS)
    rg.setMaxClusterSize(cloud.size())
    # rg.setNumberOfNeighbours(n_neighbours) # 注释
    rg.setResidualThreshold(residual_threshold)
    rg.setSmoothnessThreshold(smooth_threshold / 180 * math.pi)  # / 180 * math.pi
    rg.setCurvatureThreshold(curvature_threshold)
    child_cluster_indices = pl.vectors.PointIndices()
    rg.extract(child_cluster_indices)
    return child_cluster_indices

点云密度聚类

def DensityBasedSpatialClustering(data):
    from sklearn.cluster import DBSCAN
    dbscan = DBSCAN(eps=1,min_samples=10,metric="chebyshev")
    X = data[:,:2]
    dbscan.fit(data)
    y = dbscan.labels_
    print(y)
    plt.scatter(X[:, 0], X[:, 1], c=y)
    plt.show()

点云超体素聚类

def Supervoxel(path):
	cloud_filtered = pl.PointCloud.PointXYZRGBA()
	pl.io.load(path,cloud_filtered )
    normal = cloud_filtered.compute_normals(radius=0.3)
    sup = pl.segmentation.SupervoxelClustering.PointXYZRGBA(voxel_resolution=1,seed_resolution=2)
    sup.setNormalCloud(normal)
    sup.setInputCloud(cloud_filtered)
    sup.setNormalImportance(4.0)
    sup.setSpatialImportance(1.0)
    sup.setColorImportance(0.0)
    super_clusters = pl.vectors.map_uint32t_PointXYZRGBA()
    sup.extract(super_clusters)
    voxel_centroid_cloud = sup.getVoxelCentroidCloud()

点云曲率计算

def ShowPointNormal(cloud,k = 10):
    # 计算法线
    tree = pl.search.KdTree.PointXYZ()
    normals = pl.PointCloud.Normal()
    ne = pl.features.NormalEstimationOMP.PointXYZ_Normal()
    ne.setInputCloud(cloud)
    ne.setSearchMethod(tree)
    # ne.setRadiusSearch(0.7)
    ne.setKSearch(k)
    ne.compute(normals)
    # 计算曲率
    cur = pl.features.PrincipalCurvaturesEstimation.PointXYZ_Normal_PrincipalCurvatures()
    curvatures = pl.PointCloud.PrincipalCurvatures()
    cur.setInputCloud(cloud)
    cur.setInputNormals(normals)
    cur.setKSearch(k)
    cur.setSearchMethod(tree)
    cur.compute(curvatures)

    return normals,curvatures

点云保存

pl.io.savePLYFile(savePath,points)

点云颜色值修改

随机给点云赋予颜色、也可指定颜色

def rgb2c(r, g, b):
    return r << 16 | g << 8 | b
def(indices,child_cloud,points_cluster )
	r = int(np.random.randint(50, 255,dtype=np.uint8)* np.random.uniform(0.2,1))
	g = int(np.random.randint(50, 255,dtype=np.uint8)* np.random.uniform(0.2,1))
	b = int(np.random.randint(50, 255,dtype=np.uint8)* np.random.uniform(0.2,1))
	rgb = rgb2c(r, g, b)
	points_cluster[:, 0] = child_cloud.x
	points_cluster[:, 1] = child_cloud.y
	points_cluster[:, 2] = child_cloud.z
	points_cluster[:, 3] = rgb
	return points_cluster;

深度图转点云

def Depth2Points3d(depth_data):
    c_x = 642.771
    c_y = 365.479
    fx = 926.134
    fy = 926.12
    res_data = np.zeros((depth_data.shape[0],depth_data.shape[1],3))
    for u in range(depth_data.shape[0]):
        for v in range(depth_data.shape[1]):
            z = depth_data[u, v]
            x = (v - c_x) * z / fx
            y = (u - c_y) * z / fy
            res_data[u, v] = (x, y, z)
    return res_data

猜你喜欢

转载自blog.csdn.net/qq_43627520/article/details/129210304