Source code for openalea.phenomenal.object.image3D

# -*- 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 os
import numpy
import cv2
# ==============================================================================


[docs]class Image3D(numpy.ndarray): def __new__(cls, input_array, voxels_size=1, world_coordinate=(0, 0, 0), dtype=numpy.uint8, order='C'): if not isinstance(input_array, numpy.ndarray): raise TypeError('input_array must be a numpy.ndarray') if input_array.ndim != 3: raise ValueError("input_array must be numpy.ndarray of ndim == 3") obj = numpy.asarray(input_array, dtype=dtype, order=order).view(cls) obj.voxels_size = voxels_size obj.world_coordinate = world_coordinate return obj def __array_finalize__(self, obj): if obj is None: return self.voxels_size = getattr(obj, 'voxels_size', 1) self.world_coordinate = getattr(obj, 'world_coordinate', (0, 0, 0)) # ========================================================================== # TRANSFORM # ========================================================================== # def to_VoxelPointCloud(self, # voxels_value=1, # voxels_size=None, # world_coordinate=None): # # xx, yy, zz = numpy.where(self >= voxels_value) # # if voxels_size is None: # voxels_size = self.voxels_size # # if world_coordinate is None: # world_coordinate = self.world_coordinate # # xxx = world_coordinate[0] + xx * voxels_size # yyy = world_coordinate[1] + yy * voxels_size # zzz = world_coordinate[2] + zz * voxels_size # # voxels_position = zip(xxx, yyy, zzz) # # return VoxelGrid(voxels_position, voxels_size) # ========================================================================== # READ / WRITE # ========================================================================== def write_to_npz(self, filename): if (os.path.dirname(filename) and not os.path.exists( os.path.dirname(filename))): os.makedirs(os.path.dirname(filename)) numpy.savez_compressed(filename, image=self, voxels_size=self.voxels_size, world_coordinate=self.world_coordinate, allow_pickle=False) @staticmethod def read_from_npz(filename): npz = numpy.load(filename, allow_pickle=False) image = npz['image'] voxels_size = int(npz['voxels_size']) world_coordinate = tuple(npz['world_coordinate']) return Image3D(image, voxels_size=voxels_size, world_coordinate=world_coordinate) def write_to_stack_image(self, folder_name): if not os.path.exists(folder_name): os.makedirs(folder_name) xl, yl, zl = self.shape for i in range(zl): mat = self[:, :, i] * 255 cv2.imwrite(folder_name + '%d.png' % i, mat) # ========================================================================== # CREATION ROUTINE # ========================================================================== @staticmethod def zeros(shape, voxels_size=1, world_coordinate=(0, 0, 0), dtype=numpy.uint8, order='C'): if len(shape) != 3: raise ValueError("shape len must be equal to 3") return Image3D(numpy.zeros(shape), voxels_size=voxels_size, world_coordinate=world_coordinate, dtype=dtype, order=order) @staticmethod def zeros_like(image_3d): if not isinstance(image_3d, Image3D): raise TypeError("image_3d must be a Image3D type") if image_3d.flags['C_CONTIGUOUS']: order = 'C' else: order = 'F' return Image3D.zeros(image_3d.shape, voxels_size=image_3d.voxels_size, world_coordinate=image_3d.world_coordinate, dtype=image_3d.dtype, order=order) @staticmethod def ones(shape, voxels_size=1, world_coordinate=(0, 0, 0), dtype=numpy.uint8, order='C'): if len(shape) != 3: raise ValueError("shape len must be equal to 3") return Image3D(numpy.ones(shape), voxels_size=voxels_size, world_coordinate=world_coordinate, dtype=dtype, order=order) @staticmethod def ones_like(image_3d): if not isinstance(image_3d, Image3D): raise TypeError("image_3d must be a Image3D type") if image_3d.flags['C_CONTIGUOUS']: order = 'C' else: order = 'F' return Image3D.ones(image_3d.shape, voxels_size=image_3d.voxels_size, world_coordinate=image_3d.world_coordinate, dtype=image_3d.dtype, order=order)