使用Python代码实现对txt格式点云数据的半径滤波

任务需求:

对包含了x y z r g b六中信息的点云数据(txt)格式进行半径滤波,我的数据是按照S3DIS来制作的,之前查了很多资料发现都没有直接对txt格式进行操作的.直接见代码吧

代码

import numpy as np
from sklearn.neighbors import NearestNeighbors
import os

def radius_filter(points, radius, min_num):
    # 对原始点云数据进行半径滤波,返回处理后的点的索引
    neigh = NearestNeighbors(radius=radius)
    neigh.fit(points)
    indices = neigh.radius_neighbors(points, return_distance=False)

    filtered_indices = []
    for i, neighbors in enumerate(indices):
        if len(neighbors) > min_num:
            filtered_indices.append(i)

    return points[filtered_indices, :], filtered_indices, np.concatenate(indices)
# 读取点云数据
# 定义输入和输出文件夹的路径
input_folder = ".."
output_folder = ".."
# 遍历输入文件夹中的所有子文件夹
for subdir, dirs, files in os.walk(input_folder):
    # 构造输出子文件夹的路径
    output_subdir = os.path.join(output_folder, subdir[len(input_folder)+1:])

    # 遍历子文件夹中的所有txt文件
    for filename in files:
        if filename.endswith(".txt"):
            print("正在处理")
            # 构造输入和输出文件的路径
            input_path = os.path.join(subdir, filename)
            output_path = os.path.join(output_subdir, filename)

            data = np.genfromtxt(input_path, delimiter=' ')

        # 将点云数据分成点和颜色两部分
            points = data[:, :3]
            colors = data[:, 3:]

            filtered_points, filtered_indices, indices = radius_filter(points, 0.2, 20)

            filtered_colors = colors[filtered_indices, :]

         # 将过滤后的点云数据和颜色数据合并
            filtered_data = np.concatenate((filtered_points, filtered_colors), axis=1)
            os.makedirs(output_subdir, exist_ok=True)
         # 将处理后的点云数据保存到输出文件中
            np.savetxt(output_path, filtered_data, delimiter=' ', fmt='%.6f %.6f %.6f %d %d %d')

其中input_folder 和output_folder需要自己来设置读取文件的路径和保存录取,代码可以自动根据读取文件夹中去寻找txt文件,处理后的文件会保存到output_folder,另外只需要指定最大的目录即可(参考S3DIS数据集),保存的output_folder文件夹会自动创建与读取路径中相同命名的子文件夹并保存对应的txt文件。同时可以修改radius_filter(points, 0.2, 20)中后两个参数来指定半径和邻近点的个数。

针对比较大的数据

以下是优化后的代码,主要采用分块读取文件来处理,防止点云数据过大造成内存溢出,这里我设置的块的大小是20w

import numpy as np
import pandas as pd
from sklearn.neighbors import NearestNeighbors
import os
import time

def radius_filter(points, radius, min_num):
    # 对原始点云数据进行半径滤波,返回处理后的点的索引
    neigh = NearestNeighbors(radius=radius)
    neigh.fit(points)
    indices = neigh.radius_neighbors(points, return_distance=False)

    filtered_indices = []
    for i, neighbors in enumerate(indices):
        if len(neighbors) > min_num:
            filtered_indices.append(i)

    return points[filtered_indices, :], filtered_indices, np.concatenate(indices)

# 定义输入和输出文件夹的路径
input_folder = "..."
output_folder = "..."

#分块读取的块大小
chunk_size = 200000

#创建所有输出目录
for subdir, dirs, files in os.walk(input_folder):
    output_subdir = os.path.join(output_folder, subdir[len(input_folder)+1:])
    os.makedirs(output_subdir, exist_ok=True)

    # 遍历子文件夹中的所有txt文件, 并进行处理
    for filename in files:
        if filename.endswith(".txt"):
            input_path = os.path.join(subdir, filename)
            output_path = os.path.join(output_subdir, filename)

            #使用pandas分块读取点云数据
            start_time = time.time()
            reader = pd.read_csv(input_path, delimiter=' ', header=None, chunksize=chunk_size)

            # 创建临时输出文件
            temp_output_path = output_path + ".temp"
            temp_output_file = open(temp_output_path, 'w')

            #循环读取块,进行处理并将结果写入临时输出文件
            for data in reader:
                points = data.iloc[:, :3].values
                colors = data.iloc[:, 3:].values

                filtered_points, filtered_indices, indices = radius_filter(points, 0.2, 20)

                filtered_colors = colors[filtered_indices, :]

                #将过滤后的点云数据和颜色数据合并
                filtered_data = np.concatenate((filtered_points, filtered_colors), axis=1)

                #将处理后的点云数据保存到临时输出文件中
                np.savetxt(temp_output_file, filtered_data, delimiter=' ', fmt='%.6f %.6f %.6f %d %d %d')

                print(f"处理完毕: {temp_output_path}")

            # 关闭临时输出文件
            temp_output_file.close()

            #合并去重结果,并删除临时文件
            merged_data = pd.read_csv(temp_output_path, delimiter=' ', header=None).drop_duplicates().values
            np.savetxt(output_path, merged_data, delimiter=' ', fmt='%.6f %.6f %.6f %d %d %d')
            os.remove(temp_output_path)

            print(f"文件 {output_path} 处理完毕, 用时:{time.time()-start_time:.2f}秒")

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值