# HG changeset patch # User imgteam # Date 1709895641 0 # Node ID f10112b317a15052f5203f8b3bcaf86caeadc66a planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/morphological_operations commit c6d2a4fb19b54c804029ae3d52eb9fb2619e4265 diff -r 000000000000 -r f10112b317a1 morphological_operations.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/morphological_operations.py Fri Mar 08 11:00:41 2024 +0000 @@ -0,0 +1,93 @@ +import argparse + +import numpy as np +import scipy.ndimage as ndi +import skimage.io +import skimage.morphology as morph + + +def create_selem(args): + """ + Creates structuring element based on commandline arguments. + """ + assert args.selem_shape in ( + 'square', + 'disk', + ) + + if args.selem_shape == 'square': + return np.ones((args.selem_size, args.selem_size)) + + elif args.selem_shape == 'disk': + return morph.disk(args.selem_size) + + +def apply_operation(args, im): + """ + Applies morphological operation to a 2-D single-channel image. + """ + assert im.ndim == 2 + selem = create_selem(args) + values_count = len(np.unique(im)) + if values_count <= 2: + im_proxy = np.zeros(im.shape, bool) + im_proxy[im == im.max()] = True + result_proxy = apply_binary_operation(args, im_proxy, selem) + result = np.full(im.shape, im.min(), im.dtype) + result[result_proxy] = im.max() + return result + else: + return apply_intensity_based_operation(args, im, selem) + + +def apply_intensity_based_operation(args, im, selem): + operations = { + 'erosion': ndi.grey_erosion, + 'dilation': ndi.grey_dilation, + 'opening': ndi.grey_opening, + 'closing': ndi.grey_closing, + } + if args.operation in operations: + operation = operations[args.operation] + return operation(input=im, structure=selem) + else: + raise ValueError(f'Operation "{args.operation}" not supported for this image type ({im.dtype}).') + + +def apply_binary_operation(args, im, selem): + operations = { + 'erosion': ndi.binary_erosion, + 'dilation': ndi.binary_dilation, + 'opening': ndi.binary_opening, + 'closing': ndi.binary_closing, + 'fill_holes': ndi.binary_fill_holes, + } + operation = operations[args.operation] + return operation(input=im, structure=selem) + + +if __name__ == '__main__': + + parser = argparse.ArgumentParser() + parser.add_argument('--operation', type=str) + parser.add_argument('--selem-shape', type=str) + parser.add_argument('--selem-size', type=int) + parser.add_argument('input', type=str) + parser.add_argument('output', type=str) + args = parser.parse_args() + + im = skimage.io.imread(args.input) + assert im.ndim in (2, 3), 'Input image must be two-dimensional and either single-channel or multi-channel.' + + if im.ndim == 2: + im_result = apply_operation(args, im) + + else: + ch_result_list = [] + for ch_idx in range(im.shape[2]): + ch = im[:, :, ch_idx] + ch_result = apply_operation(args, ch) + ch_result_list.append(ch_result) + im_result = np.dstack(ch_result_list) + + skimage.io.imsave(args.output, im_result) diff -r 000000000000 -r f10112b317a1 morphological_operations.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/morphological_operations.xml Fri Mar 08 11:00:41 2024 +0000 @@ -0,0 +1,133 @@ + + with SciPy + + 1.12.0 + 0 + + + operation_3443 + + + scipy + + + scipy + scikit-image + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Applies a morphological operation to a 2-D image. + For multi-channel images, the operation is applied to each channel separately. + + The following operations are supported: + + - **Erosion:** Shrink bright areas. + - **Dilation:** Grow bright areas. + - **Opening:** Erosion followed by Dilation. Erases tiny bright spots. + - **Closing:** Dilation followed by Erosion. Erases tiny dark holes. + - **Fill holes:** Fills the holes (dark areas) in binary images. + + + 10.1038/s41592-019-0686-2 + + \ No newline at end of file diff -r 000000000000 -r f10112b317a1 test-data/input1.tiff Binary file test-data/input1.tiff has changed diff -r 000000000000 -r f10112b317a1 test-data/input2.png Binary file test-data/input2.png has changed diff -r 000000000000 -r f10112b317a1 test-data/input3.png Binary file test-data/input3.png has changed diff -r 000000000000 -r f10112b317a1 test-data/output1_closing.tiff Binary file test-data/output1_closing.tiff has changed diff -r 000000000000 -r f10112b317a1 test-data/output1_dilation.tiff Binary file test-data/output1_dilation.tiff has changed diff -r 000000000000 -r f10112b317a1 test-data/output1_erosion.tiff Binary file test-data/output1_erosion.tiff has changed diff -r 000000000000 -r f10112b317a1 test-data/output1_opening.tiff Binary file test-data/output1_opening.tiff has changed diff -r 000000000000 -r f10112b317a1 test-data/output2_fill_holes.tiff Binary file test-data/output2_fill_holes.tiff has changed diff -r 000000000000 -r f10112b317a1 test-data/output3_closing.tiff Binary file test-data/output3_closing.tiff has changed diff -r 000000000000 -r f10112b317a1 test-data/output3_dilation.tiff Binary file test-data/output3_dilation.tiff has changed diff -r 000000000000 -r f10112b317a1 test-data/output3_erosion.tiff Binary file test-data/output3_erosion.tiff has changed diff -r 000000000000 -r f10112b317a1 test-data/output3_opening.tiff Binary file test-data/output3_opening.tiff has changed