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