Application on point cloud#
Load modules#
[1]:
import numpy
import pandas
import openalea.phenomenal.display.notebook as phm_display_notebook
import openalea.phenomenal.object as phm_obj
import openalea.phenomenal.segmentation as phm_seg
Load cloud point cloud#
First we define a function “read_from_xyz” to load our point cloud data
[2]:
def read_from_xyz(filename):
xyz_position = list()
with open(filename, 'r') as f:
for line in f:
values = [float(v) for v in line.split()[:3]] # load just position not color
xyz_position.append(tuple(values))
f.close()
return numpy.array(xyz_position)
Maize point cloud was found on : CharlieLeee/Maize-plant-point-cloud-dataset and cleaned mannually with CloudCompare software. 3D reconstruction is pretty bad, leaves are very noised and seems cutted.
[3]:
file_path = "maize_point_cloud.pts"
xyz_position = read_from_xyz(file_path)
phm_display_notebook.show_point_cloud(xyz_position, size=0.1)
Convert point cloud to voxel grid#
Once loaded, we attribute for each point a fictive voxel size to simulate the data like a voxel grid. More the fictive voxel size is small more the 3D voxel representation is accurate. After we normalize the pointcloud into a grid.
[4]:
fictive_voxel_size = 0.05
voxel_grid = phm_obj.VoxelGrid(numpy.array(xyz_position), fictive_voxel_size)
voxel_grid = phm_obj.VoxelGrid.from_image_3d(
voxel_grid.to_image_3d(),
voxels_value=1,
voxels_size=1, # must be integer
world_coordinate=(0.0, 0.0, 0.0))
print("Shape Image 3D:", voxel_grid.to_image_3d().shape)
phm_display_notebook.show_voxel_grid(voxel_grid, size=1)
Shape Image 3D: (134, 212, 96)
[5]:
graph = phm_seg.graph_from_voxel_grid(voxel_grid, connect_all_point=False)
src_node = tuple(max(graph.nodes(), key=lambda d: d[1]))
voxel_skeleton = phm_seg.skeletonize(voxel_grid, graph, src_node=src_node)
Skeletonization#
[6]:
phm_display_notebook.show_skeleton(voxel_skeleton, with_voxel=True, size=1.0)
Maize Segmentation#
[7]:
vms = phm_seg.maize_segmentation(voxel_skeleton, graph, stem_strategy="longest")
phm_display_notebook.show_segmentation(vms, size=1)
Maize Analysis#
[8]:
vmsi = phm_seg.maize_analysis(vms)
phm_display_notebook.show_segmentation(vmsi, size=1)
Take a look, of what kind of data is extract. (pm = phenomenal_mearsurement)
[9]:
df = pandas.DataFrame([vo.info for vo in vmsi.voxel_organs] + [vmsi.info])
df
[9]:
| pm_label | pm_sub_label | pm_voxels_volume | pm_position_tip | pm_position_base | pm_z_tip | pm_z_base | pm_length | pm_width_max | pm_width_mean | ... | pm_azimuth_angle | pm_inclination_angle | pm_full_length | pm_length_with_speudo_stem | pm_insertion_angle_vector | pm_insertion_angle | pm_length_speudo_stem | pm_leaf_number | pm_z_base_voxel | pm_number_of_leaf | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | unknown | NaN | 186 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1 | stem | NaN | 2337 | (71.0, 85.0, 44.0) | (81.0, 211.0, 61.0) | 44.0 | 61.0 | 136.316379 | 11.401754 | 7.013952 | ... | -94.317102 | 0.775932 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 2 | growing_leaf | NaN | 6907 | (2.0, 7.0, 57.0) | (71.0, 84.0, 44.0) | 57.0 | 44.0 | 119.181579 | 26.907248 | 14.662080 | ... | -122.668166 | 0.893494 | 256.497959 | 118.181579 | (-2.6956521739130435, -12.0, 0.0) | 11.526682 | -1.000000 | 7.0 | NaN | NaN |
| 3 | growing_leaf | NaN | 3556 | (71.0, 21.0, 9.0) | (75.0, 56.0, 31.0) | 9.0 | 31.0 | 46.212474 | 12.688578 | 9.697847 | ... | -91.091216 | 3.433875 | 215.545905 | 78.183037 | (0.0, -5.0, -4.444444444444445) | 33.868735 | 31.970563 | 8.0 | NaN | NaN |
| 4 | growing_leaf | NaN | 4158 | (58.0, 14.0, 47.0) | (63.0, 34.0, 48.0) | 47.0 | 48.0 | 22.388905 | 9.273618 | 5.549971 | ... | -100.784298 | 4.636406 | 214.290342 | 75.973963 | (-0.6, -3.0, 0.0) | 10.596425 | 53.585057 | 9.0 | NaN | NaN |
| 5 | mature_leaf | NaN | 567 | (77.0, 182.0, 9.0) | (80.0, 184.0, 52.0) | 9.0 | 52.0 | 64.193966 | 7.615773 | 4.439786 | ... | -120.424395 | 2.922740 | 95.239725 | NaN | (-3.4166666666666665, -6.083333333333333, -6.5) | 41.293851 | NaN | 5.0 | 53.0 | NaN |
| 6 | mature_leaf | NaN | 1329 | (128.0, 147.0, 40.0) | (85.0, 175.0, 53.0) | 40.0 | 53.0 | 60.537111 | 15.033296 | 7.700353 | ... | -41.228776 | 2.291478 | 101.122169 | NaN | (4.090909090909091, -6.0, -1.4545454545454546) | 38.177025 | NaN | 6.0 | 52.0 | NaN |
| 7 | mature_leaf | NaN | 1484 | (24.0, 120.0, 56.0) | (71.0, 152.0, 51.0) | 56.0 | 51.0 | 69.504274 | 11.874342 | 6.881522 | ... | -142.300788 | 1.645193 | 136.113911 | NaN | (-7.0, -6.384615384615385, -1.0769230769230769) | 42.978219 | NaN | 4.0 | 47.0 | NaN |
| 8 | mature_leaf | NaN | 1699 | (122.0, 85.0, 31.0) | (82.0, 134.0, 49.0) | 31.0 | 49.0 | 73.632759 | 13.379088 | 8.227598 | ... | -58.572101 | 1.979836 | 155.921159 | NaN | (1.4615384615384615, -7.0, -1.0) | 15.953872 | NaN | 2.0 | 38.0 | NaN |
| 9 | mature_leaf | NaN | 3380 | (0.0, 55.0, 86.0) | (71.0, 106.0, 49.0) | 86.0 | 49.0 | 108.748857 | 17.029386 | 9.709537 | ... | -136.528551 | 0.891515 | 222.090545 | NaN | (-8.0, -10.0, 1.105263157894737) | 36.610113 | NaN | 3.0 | 47.0 | NaN |
| 10 | mature_leaf | NaN | 3009 | (115.0, 42.0, 26.0) | (79.0, 101.0, 45.0) | 26.0 | 45.0 | 95.271833 | 21.954498 | 10.111130 | ... | -67.995238 | 1.419182 | 213.170599 | NaN | (2.2777777777777777, -9.5, -2.5) | 18.577649 | NaN | 1.0 | 23.0 | NaN |
| 11 | plant | NaN | 22575 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 9.0 |
12 rows × 25 columns