From a7220a243e2a7851f45d94e11a5b552256d596cf Mon Sep 17 00:00:00 2001 From: monadal <morgane.nadal@inria.fr> Date: Wed, 11 Mar 2020 10:29:54 +0100 Subject: [PATCH] fct for intensity normalization and find voxel dimension in micron + refractoring --- brick/processing/input.py | 39 +++++++++++++++++++++++++++++++++------ nutrimorph.py | 4 ++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/brick/processing/input.py b/brick/processing/input.py index a9a1a11..56a081f 100644 --- a/brick/processing/input.py +++ b/brick/processing/input.py @@ -32,9 +32,11 @@ from brick.general.type import array_t import numpy as np_ import sys as sy_ +from PIL import Image +from PIL.ExifTags import TAGS -def ImageVerification(image, channel): +def ImageVerification(image: array_t, channel: str) -> array_t: if image.ndim == 3: print('Your image has only one color channel.') if channel == 'RGB': @@ -59,6 +61,7 @@ def ImageVerification(image, channel): print('The image dimensions are not correct:', image.ndim, ', instead of 3 or 4.') sy_.exit(0) + # 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'): @@ -70,12 +73,13 @@ def ImageVerification(image, channel): def IntensityNormalizedImage(image: array_t) -> array_t: # - print('Relative Intensity Normalization between 0 and 1 (Not a standardization). Need to reevaluate the parameters !!!') + 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() - result = (image.astype(np_.float32) - value_min)/(value_max - value_min) + result = (image.astype(np_.float32) - value_min) / (value_max - value_min) return result @@ -92,9 +96,32 @@ def IntensityNormalizedImage(image: array_t) -> array_t: # # return result -def MetricNormalizedImage(image: array_t) -> array_t: # TODO - # - print('Image metric in converted to micrometers.') + +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: # diff --git a/nutrimorph.py b/nutrimorph.py index ca15e44..52d993c 100644 --- a/nutrimorph.py +++ b/nutrimorph.py @@ -54,6 +54,7 @@ import numpy as np_ import skimage.io as io_ import skimage.measure as ms_ from skimage.segmentation import relabel_sequential +import exifread as xf_ print(sy_.argv, sy_.argv.__len__()) @@ -89,6 +90,9 @@ start_time = tm_.time() # --- Images +voxel_micron = in_.VoxelDimensionInMicrons(data_path) + + image = io_.imread(data_path) # Image size verification - simple version without user interface -- GitLab