finished abstracting image processing engine
all imagej related code has now been moved to ijimageengine.py
This commit is contained in:
parent
7994afd01a
commit
74d7f9e603
|
@ -39,7 +39,10 @@ class IImageEngine(ABC):
|
|||
|
||||
@staticmethod
|
||||
def get_instance():
|
||||
"""Static access method."""
|
||||
"""Static access method.
|
||||
:rtype IImageEngine:
|
||||
"""
|
||||
|
||||
assert IImageEngine.__instance is not None
|
||||
return IImageEngine.__instance
|
||||
|
||||
|
@ -50,7 +53,6 @@ class IImageEngine(ABC):
|
|||
:param str out_file_path: eg './white_estimate.tiff'
|
||||
"""
|
||||
|
||||
|
||||
@abc.abstractmethod
|
||||
def compute_max(self, images_file_path):
|
||||
"""Compute for each pixel position the maximum at this position in all input images.
|
||||
|
@ -59,3 +61,36 @@ class IImageEngine(ABC):
|
|||
:rtype IImage:
|
||||
"""
|
||||
|
||||
|
||||
@abc.abstractmethod
|
||||
def perform_gray_morphology(self, image, operator, structuring_element_shape, structuring_element_radius):
|
||||
"""
|
||||
:param IImage image:
|
||||
:param str operator: eg 'open'
|
||||
:param str structuring_element_shape: eg 'square'
|
||||
:param int structuring_element_radius:
|
||||
"""
|
||||
|
||||
|
||||
@abc.abstractmethod
|
||||
def replace_border(self, image, band_width):
|
||||
"""Overwrites the outer band of the image by duplicating the value of the pixels that touch this outer band
|
||||
|
||||
:param IImage image:
|
||||
:param int band_width: width of the outer band, in pixels
|
||||
:rtype IImage:
|
||||
|
||||
adaptation for the following code from matlab telemosToolbx's estimatedwhiteFluoImageTelemos function
|
||||
outer = white_estimate;
|
||||
white_estimate = white_estimate(4:(end-3),4:(end-3));
|
||||
outer(1:3,4:(end-3))=repmat(white_estimate(1,:),3,1); # top
|
||||
outer((end-2):end,4:(end-3))=repmat(white_estimate(end,:),3,1); # bottom
|
||||
outer(:,1:3)=repmat(outer(:,4),1,3); # left
|
||||
outer(:,(end-2):end)=repmat(outer(:,end-3),1,3); # right
|
||||
white_estimate = outer;
|
||||
clear outer;
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
return image
|
||||
|
||||
|
||||
|
|
|
@ -22,6 +22,23 @@ class IJImage(IImage):
|
|||
raise NotImplementedError
|
||||
|
||||
|
||||
def imagej_run_image_command(image, command, options):
|
||||
"""performs the given imagej command on the given image
|
||||
|
||||
:param ImagePlus image:
|
||||
:param str command: imagej command (eg "Gray Morphology")
|
||||
:param str options: imagej options (eg "radius=1 type=square operator=open")
|
||||
|
||||
wrapper around IJ.run (https://imagej.nih.gov/ij/developer/api/ij/IJ.html#run-ij.ImagePlus-java.lang.String-java.lang.String-) which raises an exception on error
|
||||
"""
|
||||
IJ.run(image, command, options)
|
||||
error_message = IJ.getErrorMessage()
|
||||
if error_message is not None:
|
||||
raise Exception('The command "%s" with options "%s" failed because of the following error : %s' % (command, options, error_message))
|
||||
|
||||
|
||||
|
||||
|
||||
class IJImageEngine(IImageEngine):
|
||||
|
||||
def missing(self):
|
||||
|
@ -34,7 +51,7 @@ class IJImageEngine(IImageEngine):
|
|||
"""Computes for each pixel position the maximum at this position in all input images.
|
||||
|
||||
:param list(str) images_file_path:
|
||||
:rtype IJmage:
|
||||
:rtype IJImage:
|
||||
"""
|
||||
assert len(images_file_path) > 1
|
||||
max_image = IJ.openImage(images_file_path[0])
|
||||
|
@ -46,4 +63,35 @@ class IJImageEngine(IImageEngine):
|
|||
ic = ImageCalculator()
|
||||
ic.run("max", max_image, other_image)
|
||||
print('max_image', max_image)
|
||||
return max_image
|
||||
return IJImage(self, max_image)
|
||||
|
||||
def perform_gray_morphology(self, image, operator, structuring_element_shape, structuring_element_radius):
|
||||
"""
|
||||
:param IJImage image:
|
||||
:param str operator: eg 'open'
|
||||
:param str structuring_element_shape: eg 'square'
|
||||
:param int structuring_element_radius:
|
||||
"""
|
||||
assert operator not in ['fast open', 'fast erode'], "as of 13/09/2019, fast operators such as 'fast erode' seem broken in fiji (the resulting image is not at all similar to their slow equivalent)"
|
||||
|
||||
processor = image.ij_image.getProcessor()
|
||||
convert_to_byte = False
|
||||
if processor.getBitDepth() != 8:
|
||||
convert_to_byte = True
|
||||
min_value = processor.getMin()
|
||||
max_value = processor.getMax()
|
||||
print("warning: downgrading image to byte as imagej's Gray Morphology processing doesn't handle 16bit images (range=[%d, %d])" % (min_value, max_value))
|
||||
do_scaling = True
|
||||
image.ij_image.setProcessor(processor.convertToByte(do_scaling))
|
||||
print("before gray morphology")
|
||||
assert structuring_element_radius < 11, "the radius of the structuring element is too big (%d); using it with Fiji's 'Gray Morphology' tool would result in very long computations." % structuring_element_radius
|
||||
imagej_run_image_command(image.ij_image, "Gray Morphology", "radius=%d type=%s operator=%s" % (structuring_element_radius, structuring_element_shape, operator))
|
||||
print("after gray morphology")
|
||||
|
||||
|
||||
def replace_border(self, image, band_width):
|
||||
raise NotImplementedError()
|
||||
return image
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,74 +1,9 @@
|
|||
"""preprocessing of synchrotron images based on telemosToolbox."""
|
||||
|
||||
from ij import IJ
|
||||
from ij.plugin import ImageCalculator
|
||||
from catalog import ImageCatalog, Sequence
|
||||
from imageengine import IImageEngine
|
||||
from imagej.ijimageengine import IJImageEngine, IJImage
|
||||
|
||||
def imagej_run_image_command(image, command, options):
|
||||
"""performs the given imagej command on the given image
|
||||
|
||||
:param ImagePlus image:
|
||||
:param str command: imagej command (eg "Gray Morphology")
|
||||
:param str options: imagej options (eg "radius=1 type=square operator=open")
|
||||
|
||||
wrapper around IJ.run (https://imagej.nih.gov/ij/developer/api/ij/IJ.html#run-ij.ImagePlus-java.lang.String-java.lang.String-) which raises an exception on error
|
||||
"""
|
||||
IJ.run(image, command, options)
|
||||
error_message = IJ.getErrorMessage()
|
||||
if error_message is not None:
|
||||
raise Exception('The command "%s" with options "%s" failed because of the following error : %s' % (command, options, error_message))
|
||||
|
||||
|
||||
def compute_max(images_file_path):
|
||||
image_engine = IJImageEngine()
|
||||
return image_engine.compute_max(images_file_path)
|
||||
|
||||
def replace_border(image, band_width):
|
||||
"""Overwrites the outer band of the image by duplicating the value of the pixels that touch this outer band
|
||||
|
||||
:param ImagePlus image:
|
||||
:param int band_width: width of the outer band, in pixels
|
||||
:rtype ImagePlus:
|
||||
|
||||
adaptation for the following code from matlab telemosToolbx's estimatedwhiteFluoImageTelemos function
|
||||
outer = white_estimate;
|
||||
white_estimate = white_estimate(4:(end-3),4:(end-3));
|
||||
outer(1:3,4:(end-3))=repmat(white_estimate(1,:),3,1); # top
|
||||
outer((end-2):end,4:(end-3))=repmat(white_estimate(end,:),3,1); # bottom
|
||||
outer(:,1:3)=repmat(outer(:,4),1,3); # left
|
||||
outer(:,(end-2):end)=repmat(outer(:,end-3),1,3); # right
|
||||
white_estimate = outer;
|
||||
clear outer;
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
return image
|
||||
|
||||
|
||||
def perform_gray_morphology(image, operator, structuring_element_shape, structuring_element_radius):
|
||||
"""
|
||||
:param ImagePlus image:
|
||||
:param str operator: eg 'open'
|
||||
:param str structuring_element_shape: eg 'square'
|
||||
:param int structuring_element_radius:
|
||||
"""
|
||||
assert operator not in ['fast open', 'fast erode'], "as of 13/09/2019, fast operators such as 'fast erode' seem broken in fiji (the resulting image is not at all similar to their slow equivalent)"
|
||||
|
||||
processor = image.getProcessor()
|
||||
convert_to_byte = False
|
||||
if processor.getBitDepth() != 8:
|
||||
convert_to_byte = True
|
||||
min_value = processor.getMin()
|
||||
max_value = processor.getMax()
|
||||
print("warning: downgrading image to byte as imagej's Gray Morphology processing doesn't handle 16bit images (range=[%d, %d])" % (min_value, max_value))
|
||||
do_scaling = True
|
||||
image.setProcessor(processor.convertToByte(do_scaling))
|
||||
print("before gray morphology")
|
||||
assert structuring_element_radius < 11, "the radius of the structuring element is too big (%d); using it with Fiji's 'Gray Morphology' tool would result in very long computations." % structuring_element_radius
|
||||
imagej_run_image_command(image, "Gray Morphology", "radius=%d type=%s operator=%s" % (structuring_element_radius, structuring_element_shape, operator))
|
||||
print("after gray morphology")
|
||||
|
||||
|
||||
class WhiteEstimator(object):
|
||||
|
||||
|
@ -82,8 +17,8 @@ class WhiteEstimator(object):
|
|||
self.average_size = average_size
|
||||
|
||||
def _remove_particles(self, white_estimate):
|
||||
perform_gray_morphology(white_estimate, operator='open', structuring_element_shape='square', structuring_element_radius=(self.open_size + 1) / 2)
|
||||
perform_gray_morphology(white_estimate, operator='close', structuring_element_shape='square', structuring_element_radius=(self.close_size + 1) / 2)
|
||||
IImageEngine.get_instance().perform_gray_morphology(white_estimate, operator='open', structuring_element_shape='square', structuring_element_radius=(self.open_size + 1) / 2)
|
||||
IImageEngine.get_instance().perform_gray_morphology(white_estimate, operator='close', structuring_element_shape='square', structuring_element_radius=(self.close_size + 1) / 2)
|
||||
|
||||
def estimate_white(self, sequences, channel_ids, dark=None):
|
||||
"""Estimation of the white fluorescence image shape of synchrotron light from experimental images of Telemos microscope.
|
||||
|
@ -190,11 +125,11 @@ class WhiteEstimator(object):
|
|||
for z_index in range(sequence.num_slices):
|
||||
images_file_path.append(sequence.get_image_file_path(channel_index, frame_index, z_index))
|
||||
|
||||
white_estimate = compute_max(images_file_path)
|
||||
white_estimate = IImageEngine.get_instance().compute_max(images_file_path)
|
||||
|
||||
# modify spurious pixels on the side of the images
|
||||
try:
|
||||
replace_border(white_estimate, 3)
|
||||
IImageEngine.get_instance().replace_border(white_estimate, 3)
|
||||
except NotImplementedError as error:
|
||||
print('warning: replace_outer_frame is not implemented yet')
|
||||
|
||||
|
@ -333,7 +268,7 @@ def test_preprocessing(raw_images_root_path):
|
|||
white_estimate = white_estimator.estimate_white([sequence], ['DM300_327-353_fluo'])
|
||||
# find_white_reference_image(white_estimate, sequence.get_white())
|
||||
print(white_estimate)
|
||||
IImageEngine.get_instance().save_as_tiff( IJImage( IImageEngine.get_instance(), white_estimate ), './white_estimate.tiff' )
|
||||
IImageEngine.get_instance().save_as_tiff( white_estimate, './white_estimate.tiff' )
|
||||
print('end')
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Reference in New Issue