las2ply.py 2.48 KB
Newer Older
1
import laspy
2
3
4
5
6
7
8
9
10
from pyntcloud import PyntCloud
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
from path import Path
import numpy as np


parser = ArgumentParser(description='Convert las cloud to ply along with centroid',
                        formatter_class=ArgumentDefaultsHelpFormatter)

Clement Pinard's avatar
Clement Pinard committed
11
parser.add_argument('las', type=Path,
Clément Pinard's avatar
Clément Pinard committed
12
                    help='Path to las file. Note that this script is compatible with PLY')
Clement Pinard's avatar
Clement Pinard committed
13
14
15
16
17
18
19
20
parser.add_argument('--output_folder', metavar='PATH',
                    default=None, type=Path,
                    help="where to save ply file and txt centroid")
parser.add_argument('--verbose', '-v', action='store_true')


def load_and_convert(input_file, output_folder, verbose=False):
    output_folder.makedirs_p()
Clément Pinard's avatar
Clément Pinard committed
21
22
    ply_path = output_folder / input_file.stem + '.ply'
    txt_path = output_folder / input_file.stem + '_centroid.txt'
Clement Pinard's avatar
Clement Pinard committed
23
    file_type = input_file.ext[1:].upper()
24
25
26
27
28
    if file_type == "LAS":
        offset = np.array(laspy.file.File(input_file, mode="r").header.offset)
    else:
        offset = np.zeros(3)
    cloud = PyntCloud.from_file(input_file)
Clément Pinard's avatar
Clément Pinard committed
29
30
    if verbose:
        print(cloud.points)
31
32
33
34
35
36

    points = cloud.points
    xyz = points[['x', 'y', 'z']]
    xyz += offset
    points[['x', 'y', 'z']] = xyz
    cloud.points = points
37

Clement Pinard's avatar
Clement Pinard committed
38
39
40
41
42
43
44
45
46
    if verbose:
        print("{} file with {:,} points "
              "(centroid : [{:.2f}, {:.2f}, {:.2f}] in km) "
              "successfully loaded".format(file_type,
                                           len((cloud.points)),
                                           *(cloud.centroid/1000)))

    output_centroid = cloud.centroid
    np.savetxt(txt_path, output_centroid)
47

48
49
50
51
52
53
54
55
    points = cloud.points
    xyz = points[['x', 'y', 'z']]
    xyz -= cloud.centroid
    points[['x', 'y', 'z']] = xyz
    if (all([c in points.keys() for c in ["red", "green", "blue"]])):
        points[['red', 'green', 'blue']] = (points[['red', 'green', 'blue']] / 255).astype(np.uint8)
        invalid_color = (points["red"] > 250) & (points["green"] > 250) & (points["blue"] > 250)
        cloud.points = points[["x", "y", "z", "red", "green", "blue"]][~invalid_color]
56
57

    cloud.to_file(ply_path)
Clement Pinard's avatar
Clement Pinard committed
58
59
60
    if verbose:
        print("saved shifted cloud to {}, centroid to {}".format(ply_path, txt_path))
    return ply_path, output_centroid
61
62
63


if __name__ == '__main__':
Clement Pinard's avatar
Clement Pinard committed
64
65
66
    args = parser.parse_args()
    if args.output_folder is None:
        args.output_folder = args.las_path.parent
Clément Pinard's avatar
Clément Pinard committed
67
    load_and_convert(args.las, args.output_folder, args.verbose)