Speeding up scanner data processing
Authors: Stefan Lindgren and Carolina Larsson - Last update: 2023-11-21
Citation:
Lindgren, S. (2024). 3d-scanning - Speeding up scanner data processing with Meshlab. Zenodo. https://doi.org/10.5281/zenodo.13375326
Python and Meshlab
When working with data from terrestrial laserscanners it is common to record a lot of scans to completely record the object from every angle.
In the early stages of postprocessing, there is usually a need to go through and apply different filters to each and every one of the individual scans. This can be a really tedious task, but there is a possibility to speed it up when using Meshlab as the tool for working with scannerdata.
The developer of Meshlab has developed a Python version of Meshlab called pymeshlab. This gives the possibility to write simple scripts to handle 3d-scanner data. This tutorial contains a couple of basic scripts that can be useful.
Pymeshlab is well documented and easy to install with some basic understanding of Python.
At this writing (231103) it will only work on python versions from 3.7 up to 3.11. All necessary documentation can be found at: pymeshlab.readthedocs.io/en/latest/
There is information about installation and usage.
If you have a working python installation on your computer the only thing that needs to be installed is the pymeshlab module and it can be installed using pip:
pip3 install pymeshlab
In the documentation there are some simple tests to run to make sure that the installation works.
Scripts
Convert filetype
The first script is a simple conversion from one type of file to another, in this case .ptx to .ply, but it can easily be adapted to for other conversions.
import pymeshlab import os fp = "filepath" ## change filepath to the folder where the files that should be converted are, e.g "D:/example/”
os.makedirs(fp + "/ply") for file in os.listdir(fp): if ".ptx" in file: ms = pymeshlab.MeshSet() ms.load_new_mesh(fp + file) ms.save_current_mesh(fp +"ply/" + file.replace(".ptx", ".ply"), save_vertex_normal = True)
|
Just copy the script above to a simple texteditor. Add the right filepath and save it as a pythonfile (.py). Then run it. If it is used for other filetypes check the documentation for what is needed for those.
This script will look for all files inside the folder specified in the filepath with “ptx” in the name.
It will create a folder inside that folder called “ply” and in that save .ply versions of the ptx files.
Subsample pointclouds
In projects with a lot of scans it might be necessary to subsample the scans a bit to be able to work with all of them at once. This scripts goes through all the scans with the .ply format in a folder and subsamples each of them and saves the result in new files, named as the original files but with_sub_1cm added to them. In this case 1cm means that the subsampling has changed the pointcloud so that no point are closer to any other point than 1 cm. This can of course be changed in the script to bigger or lower values.
import pymeshlab import os fp = "filepath" ## change filepath to the folder where the files that should be subsampled are
ms = pymeshlab.MeshSet()
os.makedirs(fp + "/sub")
for file in os.listdir(fp): if ".ply" in file: ms.load_new_mesh(fp+file) ms.generate_simplified_point_cloud(radius = pymeshlab.AbsoluteValue(0.01)) p = fp+"sub/"+file.replace(".ply","") + "_sub_1cm.ply" ms.save_current_mesh(p, save_vertex_normal = True) |
Just copy the script above to a simple texteditor. Add the right filepath and save it as a Python file (.py). Then just run it.
Create mesh from pointcloud
This scripts take a pointcloud and use the filter Surface reconstruction: Screened poisson to creata a mesh. When the mesh is created the scripts runs some triming tools on it.
import pymeshlab import os
fn = "filename" ## insert the path and filename to the point cloud file
ms = pymeshlab.MeshSet() ms.load_new_mesh(fn)
source=ms.current_mesh_id()
ms.set_selection_all() print(ms.current_mesh().selected_vertex_number())
d=13 w=4 ms.generate_surface_reconstruction_screened_poisson(depth = d, pointweight = w) ms.save_current_mesh(fn.replace(".ply", "_mesh_"+str(d)+str(w)+".ply"), save_vertex_normal = True) |
The values d and w represents the reconstruction depth and interpolation weight that is used in the filter. They can be changed to other values, dont go much higher than 13 on the reconstruction depth unless it is run on a very powerful computer. 0 on the interpolation depth will give a smoother result.