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) _, _, zl = self.shape for i in range(zl): mat = self[:, :, i] * 255 cv2.imwrite(folder_name + f"{i}.png", 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, )