Convert XYZ point cloud to grayscale image
Asked Answered
C

2

5

Everyone I'm trying to convert point cloud (X, Y, Z) to the grayscale image using python. I learned that the grayscale image could be generated by a Numpy array. But what I have now is a set of points which contains X, Y and height. I wanna generate a grayscale image based on X, Y and grayscale value which is Height.

Can someone give me an idea about this? Thanks beforehand.

Rowen

Consecution answered 10/12, 2018 at 5:44 Comment(8)
which format do you have you points stored into?Ricer
@Ricer I have a pandas data-frame with dimensions of X, Y, and Height which can be easily converted to gray level. Actually, the data frame is generated by pdal package from las file.Consecution
are points uniformly spaced over all the x,y space? something like a surface? or are they scattered? if latter I'd go with a scatterplot with height as colorRicer
@Ricer I don't think they are uniformly spaced. But they're like a surface since point cloud is generated by aerial photos not lidar device. Hope it is clear.Consecution
You may want to look into scipy.interpolate. Using this module you can construct an interpolating 2D function. Evaluating this function at the pixel coordinates will give you your gray scale image.Boeschen
@PaulPanzer Ok, im gonna try this one. Thanks.Consecution
Are the X,Y coordinates of you point cloud laid out on a grid? If so, the pcolormesh plotting function from Matplotlib would be a good fit for your use case.Interpolate
@PaulPanzer Thanks for your suggestion. I tried scipy.interpolation but failed since the python kernel died every time when i do interpolation. I have no idea why. But that doesn't matter. Your idea seems working for my use case so I decided to write codes by myself.Consecution
R
4

let's assume that the X,Y are arranged so they will form a grid (which is mandatory in order to build a rectangular image). from there this is easy:

import numpy as np
import matplotlib.pyplot as plt

# generate some data
ax = np.arange(-9, 10)
X, Y = np.meshgrid(ax, ax)
Z = X ** 2 + Y ** 2

# normalize the data and convert to uint8 (grayscale conventions)
zNorm = (Z - Z.min()) / (Z.max() - Z.min()) * 255
zNormUint8 = zNorm.astype(np.uint8)

# plot result
plt.figure()
plt.imshow(zNormUint8)
Rhetorical answered 10/12, 2018 at 14:46 Comment(1)
Thanks for your idea. My question has been solved following your idea.--RowenConsecution
C
7

Thanks, guys. I just finished writing my own codes to do interpolation. But my idea is from yours. Thank you to @asaflotz and @Paul Panzer.

The thing is in my scenario, points in point cloud are not arranged well. The intervals between two nearby points are not uniform. It's impossible to use grid directly. So I picked up an unstructured method in Scipy.Interpolate which has so many practical methods can be used depending on different use case. My code below is a modified version of the example from Scipy.Interpolate.griddata.

x_range=((df.X.max()-df.X.min()))
y_range=((df.Y.max()-df.Y.min()))
grid_x, grid_y = np.mgrid[df.X.min():df.X.max():(x_range*1j), df.Y.min():df.Y.max():(y_range*1j)]
points = df[['X','Y']].values
values = df['new'].values
grid_z0 = griddata(points, values, (grid_x, grid_y), method='linear').astype(np.uint8)
im=Image.fromarray(grid_z0,'L')
im.show()

Noticed that in griddata, methods like 'linear', 'nearest', 'cubic' can be applied depending on your scenarios. Here is the grayscale elevation image generated. enter image description here

Lastly, my question has been solved basically. Please comment on this post if you have any good ideas or confusion. Thanks all!

Rowen

Consecution answered 11/12, 2018 at 4:52 Comment(0)
R
4

let's assume that the X,Y are arranged so they will form a grid (which is mandatory in order to build a rectangular image). from there this is easy:

import numpy as np
import matplotlib.pyplot as plt

# generate some data
ax = np.arange(-9, 10)
X, Y = np.meshgrid(ax, ax)
Z = X ** 2 + Y ** 2

# normalize the data and convert to uint8 (grayscale conventions)
zNorm = (Z - Z.min()) / (Z.max() - Z.min()) * 255
zNormUint8 = zNorm.astype(np.uint8)

# plot result
plt.figure()
plt.imshow(zNormUint8)
Rhetorical answered 10/12, 2018 at 14:46 Comment(1)
Thanks for your idea. My question has been solved following your idea.--RowenConsecution

© 2022 - 2024 — McMap. All rights reserved.