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