davidcaron / pye57

Read and write e57 point clouds from Python
MIT License
68 stars 42 forks source link

Trouble reading a e57 file containing multiple scans #46

Closed evbernardes closed 4 months ago

evbernardes commented 10 months ago

I am trying to read e57 files containing multiple scans. My idea is to read every scan from the file, apply the rotation, subsample everything then save as a single file with Open3D. Sadly, though, the fused pointcloud seems to be all wrong, and I imagine it is a problem related to the rotation itself (for reference, CloudCompare works correctly on my files).

Here's what I'm doing:

import numpy as np
from pathlib import Path
import pye57
import open3d as o3d
from open3d.geometry import PointCloud
from open3d.utility import Vector3dVector

#%% Parameters and input
datafile = Path("../../Data/datafile.e57")
factor = 50

#%% Assembling every scan into a data dict
e57 = pye57.E57(datafile.as_posix()) # creating once to get number of scans
N = len(e57.data3d)

def get_scan(datafile, idx, factor):

    data = e57.read_scan_raw(idx)
    # data = e57.read_scan(idx, colors=True)
    header = e57.get_header(idx)

    points = np.array([
        data['cartesianX'][::factor],
        data['cartesianY'][::factor],
        data['cartesianZ'][::factor]]).T

    colors = np.array([
        data['colorRed'][::factor],
        data['colorGreen'][::factor],
        data['colorBlue'][::factor]]).T / 255

    rotation = header.rotation_matrix
    translation = header.translation

    print(f'Scan number {idx}, done!')

    return points, colors, rotation, translation

#%% Process scans into Open3D pointclouds
pcds = []
for i in range(N):
    points, colors, rotation, translation = get_scan(datafile, i, factor)

    # Creating a Open3D pointcloud
    pcd = PointCloud()
    pcd.points = Vector3dVector(points)
    pcd.colors = Vector3dVector(colors)

    transformation = np.eye(4)
    transformation[:3, :3] = rotation
    transformation[:3, -1] = translation

    # Apply transformation
    pcd.transform(transformation)

    pcds.append(pcd)

o3d.visualization.draw_geometries(pcds)

I also tried using the PointCloud.rotate and PointCloud.translate methods instead of PointCloud.transform, did not help much though.

maxim0815 commented 10 months ago

Similar problem here. But in my case, the rotation seems to be correct, but the translation is not. First thought the header had some problems, but CC shows correct results as mentioned by @evbernardes

evbernardes commented 10 months ago

Also tried using read_scan with transform=True, same problem.

dancergraham commented 9 months ago

Hello, can you provide a file which exhibits this problem ? Can you try with the e57 library - pip install e57 to see whether it is handled correctly ? Note that that library will only give the whole file at the moment, not the separate scans.

maxim0815 commented 4 months ago

Unfortunately not possible. The file has too many scan points and is too large for me to load. But I also tried it with a different file. The translations do not match there either.

dancergraham commented 4 months ago

Ok with no sample file it will be hard for anyone to investigate. Opening a file in cloudcompare, cropping and/or subsampling it to a very small size, saving, checking that the problem remains with pye57 and writing a comparison of the expected results with cloudcompare Vs the buggy results with pye57 would really help to start debugging this...

maxim0815 commented 4 months ago

Thanks for the quick reply. I debugged the files and code myself and found the bug in my writing routine. My problem is not related to @evbernardes . Sorry for the extra work. The issue can be closed as it works as it should from my perspective.

dancergraham commented 4 months ago

Ok thanks I'm closing this for now as I can't reproduce the issue and it is working correctly for you