Newer
Older
# Contributor(s): Eric Debreuve (since 2019), Morgane Nadal (2020)
#
# 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_
NADAL Morgane
committed
from PIL import Image
from PIL.ExifTags import TAGS
NADAL Morgane
committed
def ImageVerification(image: array_t, channel: str) -> array_t:
if image.ndim == 3:
print('Your image has only one color channel.')
if channel == 'RGB':
print('"RGB" channels are specified in the parameters. The image dimensions are not correct:', image.ndim,
', instead of 4.')
sy_.exit(0)
elif image.ndim == 4:
if channel == 'R' or channel == 'G' or channel == 'B':
print('The image has multiple color channels. The channel', channel,
'is specified in the parameters.')
for idx, color in enumerate('RGB'):
if channel == color:
image = image[:, :, :, idx]
return image
elif channel == 'RGB':
print('"RGB" channels are specified in the parameters. The program does not handle multiple channels for '
'now.')
sy_.exit(0)
elif image.ndim != 4 and image.ndim != 3:
print('The image dimensions are not correct:', image.ndim, ', instead of 3 or 4.')
sy_.exit(0)
NADAL Morgane
committed
# if channel != 'RGB' and image.ndim == 4:
# print('The image has multiple color channels. The channel', channel, 'was specified in the parameters.')
# for idx, color in enumerate('RGB'):
# if channel == color:
# image = image[:, :, :, idx]
# elif channel == 'RGB' and image.ndim == 3:
# print('WARNING. The 3 RGB color channels were selected in the parameters but the image has only one channel.')
def IntensityNormalizedImage(image: array_t) -> array_t:
NADAL Morgane
committed
print(
'Relative Intensity Normalization between 0 and 1 (Not a standardization). Need to reevaluate the parameters !!!')
value_max = image.astype(np_.float32).max()
value_min = image.astype(np_.float32).min()
NADAL Morgane
committed
result = (image.astype(np_.float32) - value_min) / (value_max - value_min)
# 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
committed
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
def VoxelDimensionInMicrons(data_path: str) -> array_t:
# TODO Verify if metadata are in the same format for all the images - if not, add a raise error ?
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 idaxe, axe in enumerate('XYZ'):
idvox = metadata.find('dblVoxel' + axe) # Get the index of the voxel size for the axe X, Y, Z
idvox += 15
while metadata[idvox] != '\n':
voxel_size[idaxe] += metadata[idvox]
idvox += 1
voxel_size = np_.asarray(list(map(float, voxel_size)))
voxel_size_microns = 1.0e6 * voxel_size
print('Voxel dimension in the image is [X Y Z] =', voxel_size_microns, 'in microns. WARNING this method highly '
'depends on the format of the metadata.')
return voxel_size_microns
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