Mentions légales du service

Skip to content
Snippets Groups Projects
input.py 6.33 KiB
Newer Older
DEBREUVE Eric's avatar
DEBREUVE Eric committed
# Copyright CNRS/Inria/UNS
# Contributor(s): Eric Debreuve (since 2019), Morgane Nadal (2020)
DEBREUVE Eric's avatar
DEBREUVE Eric committed
#
# eric.debreuve@cnrs.fr
#
# This software is governed by the CeCILL  license under French law and
# abiding by the rules of distribution of free software.  You can  use,
# modify and/ or redistribute the software under the terms of the CeCILL
# license as circulated by CEA, CNRS and INRIA at the following URL
# "http://www.cecill.info".
#
# As a counterpart to the access to the source code and  rights to copy,
# modify and redistribute granted by the license, users are provided only
# with a limited warranty  and the software's author,  the holder of the
# economic rights,  and the successive licensors  have only  limited
# liability.
#
# In this respect, the user's attention is drawn to the risks associated
# with loading,  using,  modifying and/or developing or reproducing the
# software by the user in light of its specific status of free software,
# that may mean  that it is complicated to manipulate,  and  that  also
# therefore means  that it is reserved for developers  and  experienced
# professionals having in-depth computer knowledge. Users are therefore
# encouraged to load and test the software's suitability as regards their
# requirements in conditions enabling the security of their systems and/or
# data to be ensured and,  more generally, to use and operate it in the
# same conditions as regards security.
#
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL license and that you accept its terms.

from brick.general.type import array_t
import numpy as np_
from PIL import Image
from PIL.ExifTags import TAGS
def ImageVerification(image: array_t, channel: str) -> array_t:
    #
    # The image must not be constant
    if image.max() == image.min():
        raise ValueError('The input image should not be constant.')

    # Verification of the dimension of the image and its coherence with the parameters (channel)
    elif image.ndim == 3:
        if channel is not None:
            raise ValueError('The image has only 3 dimensions. However, a value for the "channel" parameter is '
                             'specified. Give the channel the value None')

    elif image.ndim == 4:
        if channel == 'R' or channel == 'G' or channel == 'B':
            # not changed into if --channel in 'RGB'-- because if channel='RG' => True.
            print('The image has multiple color channels. The channel', channel,
                  'is specified in the parameters.')
            image = image[:, :, :, 'RGB'.find(channel)]

            # The obtained image must not be constant
            if image.max() == image.min():
                raise ValueError('The input image should not be constant.')

        else:
            raise ValueError('The image has multiple color channels. Error in the value of the parameter channel.')

    elif image.ndim != 4 and image.ndim != 3:
        raise ValueError(f'The image dimensions are not correct: {image.ndim}, instead of 3 or 4.')

def IntensityNormalizedImage(image: array_t) -> array_t:
    '''
    Relative normalization of the image between 0 and 1.
    No division per 0 since the image should not be constant (ImageVerification function).
    '''
DEBREUVE Eric's avatar
DEBREUVE Eric committed
    #
    print('Relative Intensity Normalization between 0 and 1. Need to reevaluate the parameters !!!')
DEBREUVE Eric's avatar
DEBREUVE Eric committed

    value_max = image.max()
    value_min = image.min()
    result = (image.astype(np_.float32) - value_min) / float(value_max - value_min)
DEBREUVE Eric's avatar
DEBREUVE Eric committed

    return result
DEBREUVE Eric's avatar
DEBREUVE Eric committed

    # print(
    #     "This normalization does not bring anything; left as is for now to avoid the need for changing prms"
    # )
    # nonextreme_values = image[np_.logical_and(image > 0.0, image < image.max())]
    #
    # if nonextreme_values.size > 0:
    #     nonextreme_avg = nonextreme_values.mean()
    #     result = image.astype(np_.float32) / nonextreme_avg
    # else:
    #     result = image.astype(np_.float32)
    #
    # return result

NADAL Morgane's avatar
NADAL Morgane committed
def FindVoxelDimensionInMicron(data_path: str) -> array_t:
    #
    if size_voxel_in_micron is not None:
        return np_.array(size_voxel_in_micron)

    else:
        print('The size of a voxel is not specified in the parameters.')

        try:
            with Image.open(data_path) as img:  # Find the voxels dimensions in micron in the metadata.
                meta_dict = {TAGS.get(key, 'missing'): img.tag[key] for key in
                             img.tag}  # Use the exif tags into the image metadata
            # Decode the tags text
            metadata = meta_dict['missing'].decode('utf8')  # Decode the tags text
            metadata = metadata.replace('\x00', '')
            voxel_size = []  # Initialize the list of voxel size in str
            for axe in 'XYZ':
                pattern = 'Voxel' + axe + '.+\= (\d.+E.\d.)'  # Regular expression
                voxel_size.append(re.findall(pattern, metadata)[0])
            voxel_size = np_.array(list(map(float, voxel_size)))
NADAL Morgane's avatar
NADAL Morgane committed
            voxel_size_micron = 1.0e6 * voxel_size
            print('Voxel dimension in the image is [X Y Z] =', voxel_size_micron, 'in micron.')
            return voxel_size_micron
        except:
            print('Unable to find the voxel dimensions in micron in the metadata. Please specify it in the parameters.')
DEBREUVE Eric's avatar
DEBREUVE Eric committed

NADAL Morgane's avatar
NADAL Morgane committed
def ToPixel(micron: float, voxel_size_micron: array_t) -> int:
    # Conversion of pixels into micron. Used in morphomath (disk structuring element mp_.disk(n_pixel)).
    # Assumes that the axes X and Y have the same ratio pixel:micron.
    return round(micron/voxel_size_micron[0])
NADAL Morgane's avatar
NADAL Morgane committed
def ToMicron(pixel: int, voxel_size_micron: array_t) -> float:
    # May not be used. if not used, delete.
NADAL Morgane's avatar
NADAL Morgane committed
    # Conversion of micron into pixels.
    # Assumes that the axes X and Y have the same ratio pixel:micron.
    return float(pixel * voxel_size_micron[0])
DEBREUVE Eric's avatar
DEBREUVE Eric committed
def DijkstraCosts(image: array_t, som_map: array_t, ext_map: array_t) -> array_t:
    #
    # TODO: Ideally, the extension part should be dilated
    # but in ext-ext connections, there must not be dilation around the current or the other exts
    # (current ext plays the role of a soma in soma-ext step)
    #
    dijkstra_costs = 1.0 / (image + 1.0)
    dijkstra_costs[np_.logical_or(som_map > 0, ext_map > 0)] = np_.inf

    return dijkstra_costs