Point cloud processing based on Open3D 6-point cloud denoising

When we obtain point cloud data from scanning equipment, the data will contain noise and artifacts. The noise characteristics of the point cloud include unreal points, isolated points, and irregularities. The device is removed based on the noise characteristics;

Statistical Filtering Statistical Outlier Removal (SOR) (removal of outliers)

  • The idea of ​​filtering
    is to perform a statistical analysis on the neighborhood of each point, and calculate the average distance from it to all adjacent points. Assuming that the obtained result is a Gaussian distribution whose shape is determined by the mean and standard deviation, then points whose average distance is outside the standard range (defined by the global distance mean and variance) can be defined as outliers and obtained from the data removed.

  • interface function

remove_statistical_outlier(self, nb_neighbors, std_ratio, print_progress=False)

insert image description here
When the average distance between the judgment point and the nb_neighbors neighboring points is greater than [average distance + std_ratio*σ], it is judged as a noise point, and std_ratio=2 or 3 is generally taken as the limit error;

  • test
import open3d as o3d
# 加载点云
pcd = o3d.io.read_point_cloud("./data/desk.pcd")
# 统计滤波
k = 20  # K邻域点的个数
μ = 2.0  # 标准差乘数
sor_pcd, idx = pcd.remove_statistical_outlier(k, μ)#当判断点的k近邻的平均距离大于【平均距离+μ*σ】,即判定为噪声点,一般取μ=2或3为极限误差
sor_pcd.paint_uniform_color([0, 0, 1])
# 提取噪声点云
sor_noise_pcd = pcd.select_by_index(idx, invert=True)
sor_noise_pcd.paint_uniform_color([1, 0, 0])
o3d.visualization.draw_geometries([sor_pcd,sor_noise_pcd], window_name="SOR")

insert image description here

Radius Outier Removal

  • The filtering idea
    traverses all points of the point cloud after the threshold parameter MinPts is given. For any point in the point cloud, suppose there are K points within its radius R. When K<MinPts, the point can be identified as a noise point, and the Click Remove.

  • interface function

remove_radius_outlier(self, nb_points, radius, print_progress=False)

insert image description here
Among them, nb_points: the minimum number of points in the neighborhood sphere, less than this number is a noise point;
radius: the radius of the neighborhood;
when the average distance of nb_points neighbors of the judgment point is greater than [average distance + μ*σ], it is judged as noise point;

  • test
import open3d as o3d

# 加载点云
pcd = o3d.io.read_point_cloud("./data/desk.pcd")
# 半径滤波
MinPts = 5  # 邻域球内的最少点个数,小于该个数为噪声点
R = 0.05    # 邻域半径大小

# pc 去噪后的点云
# idx 去噪保留的点索引
pc, idx = pcd.remove_radius_outlier(MinPts, R)

pc.paint_uniform_color([0, 0, 1])
ror_noise_pcd = pcd.select_by_index(idx,invert = True)
ror_noise_pcd.paint_uniform_color([1, 0, 0])
o3d.visualization.draw_geometries([pc, ror_noise_pcd], window_name="半径滤波")

insert image description here

Guide filtering Guilter Filter

  • Filtering idea
    guided filtering assumes that the point cloud has a good function of retaining edge information after a linear transformation; Guided Filter is generally used to perform noise reduction and other processing on 2D images. In fact, 3D point cloud can be denoised after a slight modification . The Guided Filter algorithm for point clouds can be summarized as
  1. Calculate the field N ( i ) N ( i ) of a certain point pi in the point cloudN(i)

  2. N ( i ) N ( i )The mean ui u_iof all points in N ( i )uiand covariance Σ i Σ_iSi

  3. Calculate A k A_k according to the formulaAkand bk b_kbk
    insert image description here

  4. q i = A k p i + b k q_i =A_k p_i +b_k qi=Akpi+bk, output qi q_iqias a pair of points pi p_ipiThe filtering result;

import numpy as np
import open3d as o3d

#guild filter
def guided_filter(pcd, radius, epsilon):
    kdtree = o3d.geometry.KDTreeFlann(pcd)
    points_copy = np.array(pcd.points)
    points = np.asarray(pcd.points)
    num_points = len(pcd.points)

    for i in range(num_points):
        k, idx, _ = kdtree.search_radius_vector_3d(pcd.points[i], radius)
        if k < 3:
            continue

        neighbors = points[idx, :]
        mean = np.mean(neighbors, 0)
        cov = np.cov(neighbors.T)
        e = np.linalg.inv(cov + epsilon * np.eye(3))

        A = cov @ e
        b = mean - A @ mean

        points_copy[i] = A @ points[i] + b

    pcd.points = o3d.utility.Vector3dVector(points_copy)


#添加噪声
def add_noise(pcd, sigma):
    points = np.asarray(pcd.points)
    noise = sigma * np.random.randn(points.shape[0], points.shape[1])
    points += noise



pcd = o3d.io.read_point_cloud('./data/bunny.ply')
add_noise(pcd, 0.004)
o3d.visualization.draw_geometries([pcd],window_name="rawPointCloud")
guided_filter(pcd, 0.01, 0.1)
guided_filter(pcd, 0.01, 0.1)
o3d.visualization.draw_geometries([pcd],window_name="guildFilter")


insert image description here
insert image description here

Supongo que te gusta

Origin blog.csdn.net/zfjBIT/article/details/130914452
Recomendado
Clasificación