Mercurial > repos > imgteam > morphological_operations
view morphological_operations.py @ 0:f10112b317a1 draft
planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/morphological_operations commit c6d2a4fb19b54c804029ae3d52eb9fb2619e4265
author | imgteam |
---|---|
date | Fri, 08 Mar 2024 11:00:41 +0000 |
parents | |
children | 4e25befab102 |
line wrap: on
line source
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)