Source code for openalea.phenomenal.mesh.routines

# -*- python -*-
#
#       Copyright INRIA - CIRAD - INRA
#
#       Distributed under the Cecill-C License.
#       See accompanying file LICENSE.txt or copy at
#           http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html
#
# ==============================================================================
from __future__ import division, print_function, absolute_import

import numpy
import cv2
# ==============================================================================

__all__ = ["normals",
           "centers",
           "project_mesh_on_image",
           "median_color_from_images"]

# ==============================================================================


def median_color_from_images(vertices, faces, calibration, images):
    """ Return the colors of each faces according the median of their color list
    in the faces projected images.

    Parameters
    ----------

    vertices : [(x, y, z), ...]
        Spatial coordinates for unique mesh vertices.

    faces : [(V1, V2, V3), ...]
        Define triangular faces via referencing vertex indices from vertices.
        This algorithm specifically outputs triangles, so each face has exactly
        three indices

    calibration: projection function

    images: images[id_camera][angle] = imaga

    Returns
    -------

    """
    height, length, _ = images["side"][0].shape
    img = numpy.zeros((height, length), dtype=numpy.uint8)

    angles = numpy.array(range(0, 360, 30)).astype(float)

    colors = list()
    for ind, (i, j, k) in enumerate(faces):
        pt1, pt2, pt3 = vertices[i], vertices[j], vertices[k]
        arr = numpy.array([pt1, pt2, pt3])

        cc = list()
        for angle in angles:
            pts = calibration.get_projection(angle)(arr).astype(int)
            if pts[0][1] == pts[1][1] == pts[2][1]:
                color = images["side"][angle][(pts[:, 0], pts[:, 1])]
            else:
                cv2.fillConvexPoly(img, pts, 255)
                index = numpy.where(img == 255)
                img[index] = 0
                color = images["side"][angle][index]
            cc.append(color)

        cc = numpy.concatenate(cc, axis=0)
        color = numpy.median(cc, axis=0).astype(int)
        colors.append(color)

    colors = map(tuple, colors)

    return colors


[docs]def normals(vertices, faces): """ Compute normal of each faces Parameters ---------- vertices : [(x, y, z), ...] Spatial coordinates for unique mesh vertices. faces : [(V1, V2, V3), ...] Define triangular faces via referencing vertex indices from vertices. This algorithm specifically outputs triangles, so each face has exactly three indices Returns ------- out : [(x, y, z), ...] List of vector direction of the normal in the same order that faces """ # Fancy indexing to define two vector arrays from triangle vertices actual_vertices = vertices[faces] a = actual_vertices[:, 0, :] - actual_vertices[:, 1, :] b = actual_vertices[:, 0, :] - actual_vertices[:, 2, :] # Find normal vectors for each face via cross product crosses = numpy.cross(a, b) crosses = crosses / (numpy.sum( crosses ** 2, axis=1) ** 0.5)[:, numpy.newaxis] return crosses
[docs]def centers(vertices, faces): """ Compute center of each faces Parameters ---------- vertices : [(x, y, z), ...] Spatial coordinates for unique mesh vertices. faces : [(V1, V2, V3), ...] Define triangular faces via referencing vertex indices from vertices. This algorithm specifically outputs triangles, so each face has exactly three indices Returns ------- out : [(x, y, z), ...] List of center of faces in the same order that faces """ v = vertices[faces] return (v[:, 0, :] + v[:, 1, :] + v[:, 2, :]) / 3.0
def project_mesh_on_image(vertices, faces, shape_image, projection): """ Return a binary image resulting of the projection of a mesh object representation (vertices, faces) with a projection function. :param vertices: list of 3d points position :param faces: list of 3-tuple index vertices :param shape_image: shape of the image :param projection: projection function :return: 2D numpy array """ vertices = numpy.array(vertices) height, length = shape_image img = numpy.zeros((height, length), dtype=numpy.uint8) # triangles = list() for i, j, k in faces: pt1, pt2, pt3 = vertices[i], vertices[j], vertices[k] arr = numpy.array([pt1, pt2, pt3]) pts = projection(arr).astype(int) if pts[0][1] == pts[1][1] == pts[2][1]: continue else: cv2.fillConvexPoly(img, pts, 255) return img