# HG changeset patch # User imgteam # Date 1765574284 0 # Node ID b2d9c92bc431e742432ef0879c7259190726b73c # Parent e2542d0ac64f51093897808c8f74c8c929b0b019 planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/2d_simple_filter/ commit a6fd77be465068f709a71d377900da99becf94d8 diff -r e2542d0ac64f -r b2d9c92bc431 creators.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/creators.xml Fri Dec 12 21:18:04 2025 +0000 @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r e2542d0ac64f -r b2d9c92bc431 filter.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/filter.py Fri Dec 12 21:18:04 2025 +0000 @@ -0,0 +1,110 @@ +import argparse +import json +from typing import ( + Any, + Callable, +) + +import giatools +import numpy as np +import scipy.ndimage as ndi +from skimage.morphology import disk + + +def image_astype(img: giatools.Image, dtype: np.dtype) -> giatools.Image: + return giatools.Image( + data=img.data.astype(dtype), + axes=img.axes, + original_axes=img.original_axes, + metadata=img.metadata, + ) + + +filters = { + 'gaussian': lambda img, sigma, order=0, axis=None: ( + apply_2d_filter( + ndi.gaussian_filter, + img if order == 0 else image_astype(img, float), + sigma=sigma, + order=order, + axes=axis, + ) + ), + 'uniform': lambda img, size: ( + apply_2d_filter(ndi.uniform_filter, img, size=size) + ), + 'median': lambda img, radius: ( + apply_2d_filter(ndi.median_filter, img, footprint=disk(radius)) + ), + 'prewitt': lambda img, axis: ( + apply_2d_filter(ndi.prewitt, img, axis=axis) + ), + 'sobel': lambda img, axis: ( + apply_2d_filter(ndi.sobel, img, axis=axis) + ), +} + + +def apply_2d_filter( + filter_impl: Callable[[np.ndarray, Any, ...], np.ndarray], + img: giatools.Image, + **kwargs: Any, +) -> giatools.Image: + """ + Apply the 2-D filter to the 2-D/3-D, potentially multi-frame and multi-channel image. + """ + result_data = None + for qtzc in np.ndindex( + img.data.shape[ 0], # Q axis + img.data.shape[ 1], # T axis + img.data.shape[ 2], # Z axis + img.data.shape[-1], # C axis + ): + sl = np.s_[*qtzc[:3], ..., qtzc[3]] # noqa: E999 + arr = img.data[sl] + assert arr.ndim == 2 # sanity check, should always be True + + # Perform 2-D filtering + res = filter_impl(arr, **kwargs) + if result_data is None: + result_data = np.empty(img.data.shape, res.dtype) + result_data[sl] = res + + # Return results + return giatools.Image(result_data, img.axes) + + +def apply_filter( + input_filepath: str, + output_filepath: str, + filter_type: str, + **kwargs: Any, +): + # Read the input image + img = giatools.Image.read(input_filepath) + + # Perform filtering + filter_impl = filters[filter_type] + res = filter_impl(img, **kwargs).normalize_axes_like(img.original_axes) + + # Adopt metadata and write the result + res.metadata = img.metadata + res.write(output_filepath, backend='tifffile') + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('input', type=str, help='Input image filepath') + parser.add_argument('output', type=str, help='Output image filepath (TIFF)') + parser.add_argument('params', type=str) + args = parser.parse_args() + + # Read the config file + with open(args.params) as cfgf: + cfg = json.load(cfgf) + + apply_filter( + args.input, + args.output, + **cfg, + ) diff -r e2542d0ac64f -r b2d9c92bc431 filter.xml --- a/filter.xml Thu Jul 18 08:51:37 2019 -0400 +++ b/filter.xml Fri Dec 12 21:18:04 2025 +0000 @@ -1,42 +1,249 @@ - - applies a standard filter to an image + + with scipy + + creators.xml + tests.xml + 1.16.3 + 0 + + + + + + + + + + + + + operation_3443 + + + galaxy_image_analysis + scipy + - scikit-image - numpy - pillow - tifffile + scipy + numpy + scikit-image + tifffile + giatools - - - + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - **What it does** + + **Applies a standard, general-purpose 2-D filter to an image.** + + Support for different image types: - Applies a standard filter to an image. + - For 3-D images, the filter is applied to all z-slices of the image. + - For multi-channel images, the filter is applied to all channels of the image. + - For time-series images, the filter is also applied for all time steps. + + Mean filters like the Gaussian filter, the box filter, or the median filter preserve both the brightness of the image, and + the range of values. This does not hold for the derivative variants of the Gaussian filter, which may produce negative values. + 10.1016/j.jbiotec.2017.07.019 diff -r e2542d0ac64f -r b2d9c92bc431 filter_image.py --- a/filter_image.py Thu Jul 18 08:51:37 2019 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -import argparse -import sys -import warnings -import numpy as np -import skimage.io -import skimage.filters -import skimage.util -from skimage.morphology import disk -from skimage import img_as_uint - -filterOptions = { - 'median' : lambda img_raw, radius: skimage.filters.median(img_raw, disk(radius)), - 'gaussian' : lambda img_raw, radius: skimage.filters.gaussian(img_raw, sigma=radius), - 'prewitt' : lambda img_raw, radius: skimage.filters.prewitt(img_raw), - 'sobel' : lambda img_raw, radius: skimage.filters.sobel(img_raw), - 'scharr' : lambda img_raw, radius: skimage.filters.scharr(img_raw), -} - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument('input_file', type=argparse.FileType('r'), default=sys.stdin, help='input file') - parser.add_argument('out_file', type=argparse.FileType('w'), default=sys.stdin, help='out file (TIFF)') - parser.add_argument('filter_type', choices=filterOptions.keys(), help='conversion type') - parser.add_argument('radius', default=3.0, type=float, help='Radius/Sigma') - args = parser.parse_args() - - img_in = skimage.io.imread(args.input_file.name) - res = img_as_uint(filterOptions[args.filter_type](img_in, args.radius)) - skimage.io.imsave(args.out_file.name, res, plugin='tifffile') diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input1_gaussian.tiff Binary file test-data/input1_gaussian.tiff has changed diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input1_median.tiff Binary file test-data/input1_median.tiff has changed diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input1_prewitt_h.tiff Binary file test-data/input1_prewitt_h.tiff has changed diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input1_prewitt_v.tiff Binary file test-data/input1_prewitt_v.tiff has changed diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input1_sobel_h.tiff Binary file test-data/input1_sobel_h.tiff has changed diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input1_sobel_v.tiff Binary file test-data/input1_sobel_v.tiff has changed diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input1_uint8.tiff Binary file test-data/input1_uint8.tiff has changed diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input2_float.tiff Binary file test-data/input2_float.tiff has changed diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input2_gaussian.tiff Binary file test-data/input2_gaussian.tiff has changed diff -r e2542d0ac64f -r b2d9c92bc431 test-data/input2_uniform.tiff Binary file test-data/input2_uniform.tiff has changed diff -r e2542d0ac64f -r b2d9c92bc431 test-data/res.tif Binary file test-data/res.tif has changed diff -r e2542d0ac64f -r b2d9c92bc431 test-data/retina_gaussian_order0.tiff Binary file test-data/retina_gaussian_order0.tiff has changed diff -r e2542d0ac64f -r b2d9c92bc431 test-data/retina_gaussian_order2_axis0.tiff Binary file test-data/retina_gaussian_order2_axis0.tiff has changed diff -r e2542d0ac64f -r b2d9c92bc431 test-data/sample.tif Binary file test-data/sample.tif has changed diff -r e2542d0ac64f -r b2d9c92bc431 test-data/scikit-image/LICENSE.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/scikit-image/LICENSE.txt Fri Dec 12 21:18:04 2025 +0000 @@ -0,0 +1,28 @@ +Files: * +Copyright: 2009-2022 the scikit-image team +License: BSD-3-Clause + + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. +. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE HOLDERS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -r e2542d0ac64f -r b2d9c92bc431 test-data/scikit-image/retina.png Binary file test-data/scikit-image/retina.png has changed diff -r e2542d0ac64f -r b2d9c92bc431 tests.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests.xml Fri Dec 12 21:18:04 2025 +0000 @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +