Synthetic Validation#

Import Statement :#

[1]:
%matplotlib inline

import matplotlib.pyplot as plt
import cv2
import collections
import numpy
import math
import pandas
import scipy.integrate

import openalea.phenomenal.data as phm_data
import openalea.phenomenal.object as phm_obj
import openalea.phenomenal.multi_view_reconstruction as phm_mvr
import openalea.phenomenal.mesh as phm_mesh
import openalea.phenomenal.display as phm_display
import openalea.phenomenal.display.notebook as phm_display_notebook
import openalea.phenomenal.segmentation as phm_seg
from openalea.phenotyping_data.fetch import fetch_all_data
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[1], line 16
     14 import openalea.phenomenal.mesh as phm_mesh
     15 import openalea.phenomenal.display as phm_display
---> 16 import openalea.phenomenal.display.notebook as phm_display_notebook
     17 import openalea.phenomenal.segmentation as phm_seg
     18 from openalea.phenotyping_data.fetch import fetch_all_data

File ~/checkouts/readthedocs.org/user_builds/phenomenal/checkouts/v1.9.9/src/openalea/phenomenal/display/notebook.py:13
     10 from __future__ import division, print_function, absolute_import
     12 import numpy
---> 13 import ipyvolume
     15 from ._order_color_map import order_color_map
     16 # ==============================================================================

ModuleNotFoundError: No module named 'ipyvolume'

1. Import synthetic data#

1.1 Select plant_number#

[2]:
calibration_dir = fetch_all_data('plant_1/calibration').parent
data_dir = fetch_all_data('synthetic_plant_1')
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[2], line 1
----> 1 calibration_dir = fetch_all_data('plant_1/calibration').parent
      2 data_dir = fetch_all_data('synthetic_plant_1')

NameError: name 'fetch_all_data' is not defined
[3]:
vertices, faces, meta_data = phm_data.synthetic_plant(data_dir)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[3], line 1
----> 1 vertices, faces, meta_data = phm_data.synthetic_plant(data_dir)

NameError: name 'data_dir' is not defined

1.2 Viewing#

[4]:
phm_display_notebook.show_synthetic_plant(vertices, faces, meta_data=None)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[4], line 1
----> 1 phm_display_notebook.show_synthetic_plant(vertices, faces, meta_data=None)

NameError: name 'phm_display_notebook' is not defined

2. Phenomenal Measurements#

2.1 Projection & binairies images#

[5]:
image_shape = (2448, 2048)
angles = range(0, 360, 30)
calibrations = phm_data.calibrations(calibration_dir)

selected = [("side", angle, (2448, 2048)) for angle in range(0, 360, 30)]
selected.append(("top", 0, (2048, 2448)))


bin_images = collections.defaultdict(dict)
for id_camera, angle, image_shape in selected:
    projection = calibrations[id_camera].get_projection(angle)
    image = phm_mesh.project_mesh_on_image(vertices, faces, image_shape, projection)
    bin_images[id_camera][angle] = image
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[5], line 3
      1 image_shape = (2448, 2048)
      2 angles = range(0, 360, 30)
----> 3 calibrations = phm_data.calibrations(calibration_dir)
      5 selected = [("side", angle, (2448, 2048)) for angle in range(0, 360, 30)]
      6 selected.append(("top", 0, (2048, 2448)))

NameError: name 'calibration_dir' is not defined
[6]:
# Display it
phm_display.show_images(
    list(bin_images["side"].values()) + list(bin_images["top"].values())
)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[6], line 3
      1 # Display it
      2 phm_display.show_images(
----> 3     list(bin_images["side"].values()) + list(bin_images["top"].values())
      4 )

NameError: name 'bin_images' is not defined

2.2 Multi-view reconstruction#

2.2.1 Associate images and projection function#

[7]:
def routine_select_ref_angle(bin_side_images):
    max_len = 0
    max_angle = None

    for angle in bin_side_images:
        x_pos, y_pos, x_len, y_len = cv2.boundingRect(
            cv2.findNonZero(bin_side_images[angle])
        )

        if x_len > max_len:
            max_len = x_len
            max_angle = angle

    return max_angle
[8]:
refs_angle_list = [routine_select_ref_angle(bin_images["side"])]

image_views = list()
for id_camera in bin_images:
    for angle in bin_images[id_camera]:
        projection = calibrations[id_camera].get_projection(angle)

        image_ref = None
        if id_camera == "side" and angle in refs_angle_list:
            image_ref = bin_images[id_camera][angle]

        inclusive = False
        if id_camera == "top":
            inclusive = True

        image_views.append(
            phm_obj.ImageView(
                bin_images[id_camera][angle],
                projection,
                inclusive=inclusive,
                image_ref=image_ref,
            )
        )
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[8], line 1
----> 1 refs_angle_list = [routine_select_ref_angle(bin_images["side"])]
      3 image_views = list()
      4 for id_camera in bin_images:

NameError: name 'bin_images' is not defined

2.2.2 Do the mul-view reconstruction#

[9]:
error_tolerance = 1
voxels_size = 4

voxel_grid = phm_mvr.reconstruction_3d(
    image_views, voxels_size=voxels_size, error_tolerance=error_tolerance
)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[9], line 5
      1 error_tolerance = 1
      2 voxels_size = 4
      4 voxel_grid = phm_mvr.reconstruction_3d(
----> 5     image_views, voxels_size=voxels_size, error_tolerance=error_tolerance
      6 )

NameError: name 'image_views' is not defined
[10]:
# Display it
phm_display_notebook.show_voxel_grid(voxel_grid, size=1)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[10], line 2
      1 # Display it
----> 2 phm_display_notebook.show_voxel_grid(voxel_grid, size=1)

NameError: name 'phm_display_notebook' is not defined

2.3 Skeletonization#

[11]:
graph = phm_seg.graph_from_voxel_grid(voxel_grid, connect_all_point=True)
voxel_skeleton = phm_seg.skeletonize(voxel_grid, graph)

# Select images
image_projection = list()
for angle in bin_images["side"]:
    projection = calibrations["side"].get_projection(angle)
    image_projection.append((bin_images["side"][angle], projection))

voxel_skeleton_denoised = phm_seg.segment_reduction(
    voxel_skeleton, image_projection, required_visible=4, nb_min_pixel=100
)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[11], line 1
----> 1 graph = phm_seg.graph_from_voxel_grid(voxel_grid, connect_all_point=True)
      2 voxel_skeleton = phm_seg.skeletonize(voxel_grid, graph)
      4 # Select images

NameError: name 'phm_seg' is not defined
[12]:
# Display it
phm_display_notebook.show_skeleton(voxel_skeleton_denoised, with_voxel=True, size=1.2)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[12], line 2
      1 # Display it
----> 2 phm_display_notebook.show_skeleton(voxel_skeleton_denoised, with_voxel=True, size=1.2)

NameError: name 'phm_display_notebook' is not defined

2.4 Cereals Segmentation#

[13]:
vms = phm_seg.maize_segmentation(voxel_skeleton_denoised, graph)
vmsi = phm_seg.maize_analysis(vms)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[13], line 1
----> 1 vms = phm_seg.maize_segmentation(voxel_skeleton_denoised, graph)
      2 vmsi = phm_seg.maize_analysis(vms)

NameError: name 'phm_seg' is not defined
[14]:
# Phenomenal measurements of each organs
pm_rows = [vo.info for vo in vmsi.voxel_organs]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[14], line 2
      1 # Phenomenal measurements of each organs
----> 2 pm_rows = [vo.info for vo in vmsi.voxel_organs]

NameError: name 'vmsi' is not defined
[15]:
# Display it
phm_display_notebook.show_segmentation(vmsi, size=1.2)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[15], line 2
      1 # Display it
----> 2 phm_display_notebook.show_segmentation(vmsi, size=1.2)

NameError: name 'phm_display_notebook' is not defined

3. Synthetic measurement#

3.1 Diplay leaf meta-data#

[16]:
phm_display_notebook.show_synthetic_plant(vertices, faces, meta_data=meta_data)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[16], line 1
----> 1 phm_display_notebook.show_synthetic_plant(vertices, faces, meta_data=meta_data)

NameError: name 'phm_display_notebook' is not defined

3.2 Extract measurements from meta-data#

[17]:
def remove_duplicate(poly, width):
    index, d = list(), dict()
    for i, item in enumerate(map(tuple, list(poly))):
        if item not in d:
            index.append(i)
            d[item] = True
    return poly[index], width[index]
[18]:
sm_rows = list()
x, y, z, r = zip(*meta_data["stem"])
polyline = numpy.array(list(zip(x, y, z))) * 10 - numpy.array([0, 0, 750])
r = numpy.array(r) * 10
polyline, r = remove_duplicate(polyline, r)

row = dict()
row["sm_label"] = "stem"
row["sm_max_width"] = max(r)
row["sm_average_width"] = numpy.mean(r)

row["sm_surface"] = scipy.integrate.simpson(
    r, x=phm_seg.compute_curvilinear_abscissa(polyline, 1)
)
row["sm_length"] = phm_seg.compute_length_organ(polyline)
angle, stem_vector_mean = phm_seg.compute_azimuth_angle(polyline)
sm_rows.append(row)

ranks = meta_data["leaf_order"]
polylines = {
    n: map(numpy.array, list(zip(*meta_data["leaf_polylines"][i])))
    for i, n in enumerate(ranks)
}

for leaf_order in polylines:
    x, y, z, r = polylines[leaf_order]
    polyline = numpy.array(list(zip(x, y, z))) * 10 - numpy.array([0, 0, 750])
    r = numpy.array(r) * 10
    polyline, r = remove_duplicate(polyline, r)

    row = dict()
    row["sm_leaf_number"] = leaf_order
    row["sm_label"] = "leaf"
    row["sm_position_tip"] = tuple(polyline[-1])
    row["sm_position_base"] = tuple(polyline[0])
    row["sm_max_width"] = max(r)
    row["sm_average_width"] = numpy.mean(r)

    row["sm_surface"] = scipy.integrate.simpson(
        r, x=phm_seg.compute_curvilinear_abscissa(polyline, 1)
    )

    row["sm_length"] = phm_seg.compute_length_organ(polyline)
    angle, vector_mean = phm_seg.compute_azimuth_angle(polyline)
    row["sm_azimuth_angle"] = angle
    insertion_angle, vector = phm_seg.compute_insertion_angle(
        polyline, stem_vector_mean
    )
    row["sm_insertion_angle_vector"] = vector
    row["sm_insertion_angle"] = insertion_angle
    row["sm_inclination_angle"] = phm_seg.compute_inclination_angle(polyline)
    row["sm_full_length"] = row["sm_length"] + polyline[0][2] + 750

    sm_rows.append(row)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[18], line 2
      1 sm_rows = list()
----> 2 x, y, z, r = zip(*meta_data["stem"])
      3 polyline = numpy.array(list(zip(x, y, z))) * 10 - numpy.array([0, 0, 750])
      4 r = numpy.array(r) * 10

NameError: name 'meta_data' is not defined

4. Measures registration#

Merge synthetic and phenomenal row measure together

[19]:
def registration_leafs(pm_rows, sm_rows):
    def cannot_registred(pm_row, sm_row):
        for label in ["stem", "plant", "unknown"]:
            if pm_row["pm_label"] == label or sm_row["sm_label"] == label:
                return True
        if math.isnan(pm_row["pm_length"]):
            return True
        return False

    def same_label(pm_row, sm_row):
        for label in ["stem", "plant"]:
            if pm_row["pm_label"] == label and sm_row["sm_label"] == label:
                return True
        return False

    rows_distance = []
    registered_row = []
    for pm_row in pm_rows:
        for sm_row in sm_rows:
            if same_label(pm_row, sm_row):
                registered_row.append((pm_row, sm_row, 0))
                continue
            if cannot_registred(pm_row, sm_row):
                continue

            pos1 = numpy.array(pm_row["pm_position_tip"])
            pos2 = numpy.array(sm_row["sm_position_tip"])
            distance = numpy.linalg.norm(pos2 - pos1)

            rows_distance.append((pm_row, sm_row, distance))

    while rows_distance:
        (pm_row, sm_row, d) = min(rows_distance, key=lambda t: t[2])
        registered_row.append((pm_row, sm_row, d))
        rows_distance = [
            v for v in rows_distance if pm_row not in v and sm_row not in v
        ]
    return registered_row
[20]:
registred_rows = list()
for pm_row, sm_row, d in registration_leafs(pm_rows, sm_rows):
    sm_row.update(pm_row)
    sm_row["distance_registration"] = d
    registred_rows.append(sm_row)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[20], line 2
      1 registred_rows = list()
----> 2 for pm_row, sm_row, d in registration_leafs(pm_rows, sm_rows):
      3     sm_row.update(pm_row)
      4     sm_row["distance_registration"] = d

NameError: name 'pm_rows' is not defined

4.2 Display result#

[21]:
df = pandas.DataFrame(registred_rows)
# df = df[df["distance_registration"] < 100]
# df_filtred_label = df[df["pm_label"] == "mature_leaf"]

# print df["sm_inclination_angle"], df["pm_inclination_angle"],

plt.plot(df["sm_full_length"], df["pm_full_length"], "k+")
plt.plot(df["sm_surface"] / 100.0, df["pm_surface"] / 100.0, "c+")
plt.plot(df["sm_inclination_angle"] * 100.0, df["pm_inclination_angle"] * 100.0, "co")
for label, color in [("mature_leaf", "b+"), ("growing_leaf", "r+"), ("stem", "g+")]:
    df_filtred_label = df[df["pm_label"] == label]
    plt.plot(df_filtred_label["sm_length"], df_filtred_label["pm_length"], color)

plt.plot(df_filtred_label["sm_length"], df_filtred_label["pm_length"], color)
plt.xlabel("Phenomenal measurements")
plt.ylabel("Synthetic measurements")

m = int(
    max(
        [
            df[k].max()
            for k in ["pm_length", "sm_length", "pm_full_length", "sm_full_length"]
        ]
    )
)
plt.plot(range(m), range(m), "k-")
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[21], line 7
      1 df = pandas.DataFrame(registred_rows)
      2 # df = df[df["distance_registration"] < 100]
      3 # df_filtred_label = df[df["pm_label"] == "mature_leaf"]
      4
      5 # print df["sm_inclination_angle"], df["pm_inclination_angle"],
----> 7 plt.plot(df["sm_full_length"], df["pm_full_length"], "k+")
      8 plt.plot(df["sm_surface"] / 100.0, df["pm_surface"] / 100.0, "c+")
      9 plt.plot(df["sm_inclination_angle"] * 100.0, df["pm_inclination_angle"] * 100.0, "co")

File ~/checkouts/readthedocs.org/user_builds/phenomenal/conda/v1.9.9/lib/python3.13/site-packages/pandas/core/frame.py:4102, in DataFrame.__getitem__(self, key)
   4100 if self.columns.nlevels > 1:
   4101     return self._getitem_multilevel(key)
-> 4102 indexer = self.columns.get_loc(key)
   4103 if is_integer(indexer):
   4104     indexer = [indexer]

File ~/checkouts/readthedocs.org/user_builds/phenomenal/conda/v1.9.9/lib/python3.13/site-packages/pandas/core/indexes/range.py:417, in RangeIndex.get_loc(self, key)
    415         raise KeyError(key) from err
    416 if isinstance(key, Hashable):
--> 417     raise KeyError(key)
    418 self._check_indexing_error(key)
    419 raise KeyError(key)

KeyError: 'sm_full_length'