Skip to content
Snippets Groups Projects
Commit 8c2077f7 authored by Maciej Wielgosz's avatar Maciej Wielgosz
Browse files

sparsification implemented

parent 64725988
Branches
No related tags found
No related merge requests found
......@@ -7,15 +7,24 @@ from scipy.spatial import ConvexHull
import logging
class SparsifyPointCloudToDensity:
class SparsifyLasBasedSqM:
def __init__(self, input_file, output_folder=None, target_density=10, verbose=False):
self.input_file = input_file
if output_folder is None:
self.output_folder = os.path.dirname(input_file)
self.target_density = target_density
self.desity = None
self.new_point_cloud_density = None
self.verbose = verbose
# Initialize logging
self.logger = logging.getLogger(__name__)
if self.verbose:
logging.info(f"Initialized with input file: {self.input_file}, target density: {self.target_density}")
self.logger.setLevel(logging.INFO)
else:
self.logger.setLevel(logging.WARNING)
self.logger.info(f"Initialized with input file: {self.input_file}, target density: {self.target_density}")
def calculate_density_convex_hull(self, las):
points_3D = np.vstack((las.x, las.y, las.z)).transpose()
......@@ -27,20 +36,18 @@ class SparsifyPointCloudToDensity:
return density
def sparsify(self, point_cloud):
density = self.calculate_density_convex_hull(point_cloud)
if self.verbose:
logging.info(f"Point cloud density: {density} points per square meter.")
self.density = self.calculate_density_convex_hull(point_cloud)
self.logger.info(f"Point cloud density: {self.density} points per square meter.")
x = point_cloud.x
keep_count = int(len(x) * (self.target_density / density))
keep_count = int(len(x) * (self.target_density / self.density))
sampled_indices = random.sample(range(len(x)), keep_count)
filtered_point_cloud = point_cloud.points[sampled_indices]
if self.verbose:
logging.info(f"Reduced point cloud size from {len(x)} to {len(filtered_point_cloud)} points.")
logging.info(f"Reduced point cloud by {(1 - len(filtered_point_cloud) / len(x)) * 100}%.")
density = self.calculate_density_convex_hull(filtered_point_cloud)
density = round(density, 2)
logging.info(f"Filtered point cloud density: {density} points per square meter.")
self.new_point_cloud_density =self.calculate_density_convex_hull(filtered_point_cloud)
self.logger.info(f"Reduced point cloud size from {len(x)} to {len(filtered_point_cloud)} points.")
self.logger.info(f"Reduced point cloud by {(1 - len(filtered_point_cloud) / len(x)) * 100}%.")
self.logger.info(f"New point cloud density: {self.new_point_cloud_density} points per square meter.")
return filtered_point_cloud
def process(self):
......@@ -48,18 +55,18 @@ class SparsifyPointCloudToDensity:
os.makedirs(self.output_folder)
inFile = laspy.read(self.input_file)
filtered_points = self.sparsify(inFile)
if self.verbose:
logging.info("Creating output laspy object")
self.logger.info("Creating output laspy object")
outFile = laspy.create(point_format=inFile.point_format, file_version=inFile.header.version)
outFile.header = inFile.header
outFile.points = filtered_points
# save the point cloud to the output folder with the same name as the input file but suffixed with _sparse and desired density
output_file_path = os.path.join(self.output_folder, os.path.basename(self.input_file).replace(".las", f"_sparse_{self.target_density}.las"))
outFile.write(output_file_path)
if __name__ == "__main__":
# Configure logging
logging.basicConfig(level=logging.INFO)
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--input_file", help="The .las file to sparsify.")
parser.add_argument("--output_folder", default=None, help="The folder where the sparse point cloud will be saved.")
......@@ -67,5 +74,5 @@ if __name__ == "__main__":
parser.add_argument("-v", "--verbose", help="Enable verbose logging", action="store_true")
args = parser.parse_args()
sparsifier = SparsifyPointCloudToDensity(args.input_file, args.output_folder, args.target_density, args.verbose)
sparsifier = SparsifyLasBasedSqM(args.input_file, args.output_folder, args.target_density, args.verbose)
sparsifier.process()
import argparse
import os
import logging
import laspy
from tqdm import tqdm
from nibio_preprocessing.sparsify_las_based_sq_m import SparsifyLasBasedSqM
class SparsifyLasBasedSqMInFolder(SparsifyLasBasedSqM):
def __init__(self, input_folder, output_folder=None, target_density=10, verbose=False):
super().__init__(input_file=None, output_folder=output_folder, target_density=target_density, verbose=verbose)
self.directory_with_point_clouds = input_folder
self.output_folder = output_folder
self.report = None
# Initialize logging for the subclass
self.logger = logging.getLogger(__name__)
if self.verbose:
self.logger.setLevel(logging.INFO)
else:
self.logger.setLevel(logging.WARNING)
def reduce_point_clouds(self):
# get paths to all point clouds in the directory and subdirectories
point_cloud_paths = []
# create output folder if it doesn't exist, if it does, delete all files in it
if not os.path.exists(self.output_folder):
os.makedirs(self.output_folder)
else:
files = os.listdir(self.output_folder)
for f in files:
os.remove(os.path.join(self.output_folder, f))
for root, dirs, files in os.walk(self.directory_with_point_clouds):
for file in files:
if file.endswith(".las"):
point_cloud_paths.append(os.path.join(root, file))
self.logger.info(f"Found {len(point_cloud_paths)} point clouds.")
# iterate over all point clouds and save outputs to the output folder
for point_cloud_path in tqdm(point_cloud_paths):
self.input_file = point_cloud_path
self.process()
# append information about the point cloud to a report as a dictionary
if self.report is None:
self.report = {
"input_file": [self.input_file],
"density": [self.density],
"target_density": [self.target_density],
"new_density": [self.new_point_cloud_density]
}
else:
self.report["input_file"].append(self.input_file)
self.report["density"].append(self.density),
self.report["target_density"].append(self.target_density),
self.report["new_density"].append(self.new_point_cloud_density)
if self.verbose:
# print the dictionary as a pandas dataframe
import pandas as pd
df = pd.DataFrame.from_dict(self.report, orient="index").transpose()
print(df)
if __name__ == "__main__":
# Configure logging
logging.basicConfig(level=logging.INFO)
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--input_folder", help="The folder with .las files to sparsify.")
parser.add_argument("-o", "--output_folder", default=None, help="The folder where the sparse point clouds will be saved.")
parser.add_argument("-d", "--target_density", help="The target density in points per square meter.", default=10, type=int)
parser.add_argument("-v", "--verbose", action="store_true", help="Print information about the process")
args = parser.parse_args()
sparsifier = SparsifyLasBasedSqMInFolder(
args.input_folder,
args.output_folder,
args.target_density,
args.verbose
)
sparsifier.reduce_point_clouds()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment