Skip to content

Commit 5d6ab63

Browse files
authored
Merge pull request #24 from artzet-s/master
Feature : Add point cloud input possibility
2 parents d07e042 + 116fce9 commit 5d6ab63

File tree

6 files changed

+142773
-24
lines changed

6 files changed

+142773
-24
lines changed
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Application on point cloud\n",
8+
"\n",
9+
"## Load modules "
10+
]
11+
},
12+
{
13+
"cell_type": "code",
14+
"execution_count": null,
15+
"metadata": {},
16+
"outputs": [],
17+
"source": [
18+
"import numpy\n",
19+
"import pandas\n",
20+
"\n",
21+
"import openalea.phenomenal.display as phm_display\n",
22+
"import openalea.phenomenal.data as phm_data\n",
23+
"import openalea.phenomenal.display.notebook as phm_display_notebook\n",
24+
"import openalea.phenomenal.object as phm_obj\n",
25+
"import openalea.phenomenal.multi_view_reconstruction as phm_mvr\n",
26+
"import openalea.phenomenal.segmentation as phm_seg"
27+
]
28+
},
29+
{
30+
"cell_type": "markdown",
31+
"metadata": {},
32+
"source": [
33+
"## Load cloud point cloud \n",
34+
"\n",
35+
"First we define a function \"read_from_xyz\" to load our point cloud data "
36+
]
37+
},
38+
{
39+
"cell_type": "code",
40+
"execution_count": null,
41+
"metadata": {},
42+
"outputs": [],
43+
"source": [
44+
"def read_from_xyz(filename):\n",
45+
"\n",
46+
" xyz_position = list()\n",
47+
" with open(filename, 'r') as f:\n",
48+
" for line in f:\n",
49+
" values = [float(v) for v in line.split()[:3]] # load just position not color\n",
50+
" xyz_position.append(tuple(values))\n",
51+
" f.close()\n",
52+
" \n",
53+
" return numpy.array(xyz_position)"
54+
]
55+
},
56+
{
57+
"cell_type": "markdown",
58+
"metadata": {},
59+
"source": [
60+
"Maize point cloud was found on : https://github.com/CharlieLeee/Maize-plant-point-cloud-dataset and cleaned mannually with CloudCompare software. 3D reconstruction is pretty bad, leaves are very noised and seems cutted. "
61+
]
62+
},
63+
{
64+
"cell_type": "code",
65+
"execution_count": null,
66+
"metadata": {},
67+
"outputs": [],
68+
"source": [
69+
"file_path = \"maize_point_cloud.pts\"\n",
70+
"xyz_position = read_from_xyz(file_path)\n",
71+
"phm_display_notebook.show_point_cloud(xyz_position, size=0.1)"
72+
]
73+
},
74+
{
75+
"cell_type": "markdown",
76+
"metadata": {},
77+
"source": [
78+
"## Convert point cloud to voxel grid\n",
79+
"\n",
80+
"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."
81+
]
82+
},
83+
{
84+
"cell_type": "code",
85+
"execution_count": null,
86+
"metadata": {},
87+
"outputs": [],
88+
"source": [
89+
"fictive_voxel_size = 0.05\n",
90+
"\n",
91+
"voxel_grid = phm_obj.VoxelGrid(numpy.array(xyz_position), fictive_voxel_size)\n",
92+
"voxel_grid = phm_obj.VoxelGrid.from_image_3d(\n",
93+
" voxel_grid.to_image_3d(),\n",
94+
" voxels_value=1,\n",
95+
" voxels_size=1, # must be integer\n",
96+
" world_coordinate=(0.0, 0.0, 0.0))\n",
97+
"\n",
98+
"print(\"Shape Image 3D:\", voxel_grid.to_image_3d().shape)\n",
99+
"\n",
100+
"phm_display_notebook.show_voxel_grid(voxel_grid, size=1)"
101+
]
102+
},
103+
{
104+
"cell_type": "code",
105+
"execution_count": null,
106+
"metadata": {},
107+
"outputs": [],
108+
"source": [
109+
"graph = phm_seg.graph_from_voxel_grid(voxel_grid, connect_all_point=False)\n",
110+
"src_node = tuple(max(graph.nodes(), key=lambda d: d[1]))\n",
111+
"voxel_skeleton = phm_seg.skeletonize(voxel_grid, graph, src_node=src_node)"
112+
]
113+
},
114+
{
115+
"cell_type": "markdown",
116+
"metadata": {},
117+
"source": [
118+
"## Skeletonization"
119+
]
120+
},
121+
{
122+
"cell_type": "code",
123+
"execution_count": null,
124+
"metadata": {},
125+
"outputs": [],
126+
"source": [
127+
"phm_display_notebook.show_skeleton(voxel_skeleton, with_voxel=True, size=1.0)"
128+
]
129+
},
130+
{
131+
"cell_type": "markdown",
132+
"metadata": {},
133+
"source": [
134+
"## Maize Segmentation"
135+
]
136+
},
137+
{
138+
"cell_type": "code",
139+
"execution_count": null,
140+
"metadata": {},
141+
"outputs": [],
142+
"source": [
143+
"vms = phm_seg.maize_segmentation(voxel_skeleton, graph, stem_strategy=\"longest\")\n",
144+
"\n",
145+
"phm_display_notebook.show_segmentation(vms, size=1)"
146+
]
147+
},
148+
{
149+
"cell_type": "markdown",
150+
"metadata": {},
151+
"source": [
152+
"## Maize Analysis"
153+
]
154+
},
155+
{
156+
"cell_type": "code",
157+
"execution_count": null,
158+
"metadata": {},
159+
"outputs": [],
160+
"source": [
161+
"vmsi = phm_seg.maize_analysis(vms)\n",
162+
"phm_display_notebook.show_segmentation(vmsi, size=1)"
163+
]
164+
},
165+
{
166+
"cell_type": "markdown",
167+
"metadata": {},
168+
"source": [
169+
"Take a look, of what kind of data is extract. (pm = phenomenal_mearsurement)"
170+
]
171+
},
172+
{
173+
"cell_type": "code",
174+
"execution_count": null,
175+
"metadata": {},
176+
"outputs": [],
177+
"source": [
178+
"df = pandas.DataFrame([vo.info for vo in vmsi.voxel_organs] + [vmsi.info])\n",
179+
"df"
180+
]
181+
},
182+
{
183+
"cell_type": "code",
184+
"execution_count": null,
185+
"metadata": {},
186+
"outputs": [],
187+
"source": []
188+
}
189+
],
190+
"metadata": {
191+
"kernelspec": {
192+
"display_name": "Python 3 (ipykernel)",
193+
"language": "python",
194+
"name": "python3"
195+
},
196+
"language_info": {
197+
"codemirror_mode": {
198+
"name": "ipython",
199+
"version": 3
200+
},
201+
"file_extension": ".py",
202+
"mimetype": "text/x-python",
203+
"name": "python",
204+
"nbconvert_exporter": "python",
205+
"pygments_lexer": "ipython3",
206+
"version": "3.13.3"
207+
}
208+
},
209+
"nbformat": 4,
210+
"nbformat_minor": 4
211+
}

0 commit comments

Comments
 (0)