Mercurial > repos > imgteam > scale_image
changeset 4:3179853faae9 draft
planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/scale_image/ commit c045f067a57e8308308cf6329060c7ccd3fc372f
author | imgteam |
---|---|
date | Thu, 04 Apr 2024 15:26:23 +0000 |
parents | d09507d3fb0e |
children | 85666e555698 |
files | creators.xml scale_image.py scale_image.xml test-data/anisotropic.png test-data/input1_binary_rgb.png test-data/input2_normalized.tiff test-data/input3_not_normalized.tiff test-data/normalized.tiff test-data/not_normalized.tiff test-data/out.png test-data/out2.png test-data/sample1.png test-data/uniform.png test-data/uniform_binary.png tests.xml |
diffstat | 15 files changed, 220 insertions(+), 61 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/creators.xml Thu Apr 04 15:26:23 2024 +0000 @@ -0,0 +1,23 @@ +<macros> + + <xml name="creators/bmcv"> + <organization name="Biomedical Computer Vision Group, Heidelberg Universtiy" alternateName="BMCV" url="http://www.bioquant.uni-heidelberg.de/research/groups/biomedical_computer_vision.html" /> + <yield /> + </xml> + + <xml name="creators/alliecreason"> + <person givenName="Allison" familyName="Creason"/> + <yield/> + </xml> + + <xml name="creators/bugraoezdemir"> + <person givenName="Bugra" familyName="Oezdemir"/> + <yield/> + </xml> + + <xml name="creators/thawn"> + <person givenName="Till" familyName="Korten"/> + <yield/> + </xml> + +</macros>
--- a/scale_image.py Fri Nov 10 14:23:33 2023 +0000 +++ b/scale_image.py Thu Apr 04 15:26:23 2024 +0000 @@ -1,38 +1,50 @@ import argparse import sys -import scipy.misc +import numpy as np import skimage.io import skimage.transform +import skimage.util from PIL import Image -def scale_image(input_file, output_file, scale, order=1): +def scale_image(input_file, output_file, scale, order, antialias): Image.MAX_IMAGE_PIXELS = 50000 * 50000 - img_in = skimage.io.imread(input_file) - if order == 0: - interp = 'nearest' - elif order == 1: - interp = 'bilinear' - elif order == 2: - interp = 'bicubic' + im = skimage.io.imread(input_file) + + # Parse `--scale` argument if ',' in scale: - scale = scale[1:-1].split(',') - scale = [int(i) for i in scale] - elif '.' in scale: + scale = [float(s.strip()) for s in scale.split(',')] + assert len(scale) <= im.ndim, f'Image has {im.ndim} axes, but scale factors were given for {len(scale)} axes.' + scale = scale + [1] * (im.ndim - len(scale)) + + else: scale = float(scale) - else: - scale = int(scale) - res = scipy.misc.imresize(img_in, scale, interp=interp) + + # For images with 3 or more axes, the last axis is assumed to correspond to channels + if im.ndim >= 3: + scale = [scale] * (im.ndim - 1) + [1] + + # Do the scaling + res = skimage.transform.rescale(im, scale, order, anti_aliasing=antialias, preserve_range=True) + + # Preserve the `dtype` so that both brightness and range of values is preserved + if res.dtype != im.dtype: + if np.issubdtype(im.dtype, np.integer): + res = res.round() + res = res.astype(im.dtype) + + # Save result skimage.io.imsave(output_file, res) 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 (PNG)') - parser.add_argument('scale', type=str, help='fraction scaling factor(float), percentage scaling factor(int), output size(tuple(height,width))') # integer option not implemented in galaxy wrapper - parser.add_argument('order', type=int, default=1, help='interpolation method') + parser.add_argument('input_file', type=argparse.FileType('r'), default=sys.stdin) + parser.add_argument('out_file', type=argparse.FileType('w'), default=sys.stdin) + parser.add_argument('--scale', type=str, required=True) + parser.add_argument('--order', type=int, required=True) + parser.add_argument('--antialias', default=False, action='store_true') args = parser.parse_args() - scale_image(args.input_file.name, args.out_file.name, args.scale, args.order) + scale_image(args.input_file.name, args.out_file.name, args.scale, args.order, args.antialias)
--- a/scale_image.xml Fri Nov 10 14:23:33 2023 +0000 +++ b/scale_image.xml Thu Apr 04 15:26:23 2024 +0000 @@ -1,5 +1,14 @@ -<tool id="ip_scale_image" name="Scale image" version="0.4-2"> +<tool id="ip_scale_image" name="Scale image" version="@TOOL_VERSION@+galaxy@VERSION_SUFFIX@" profile="20.05"> <description>with scikit-image</description> + <macros> + <import>creators.xml</import> + <import>tests.xml</import> + <token name="@TOOL_VERSION@">0.18.3</token> + <token name="@VERSION_SUFFIX@">0</token> + </macros> + <creator> + <expand macro="creators/bmcv" /> + </creator> <edam_operations> <edam_operation>operation_3443</edam_operation> </edam_operations> @@ -8,64 +17,84 @@ <xref type="biii">scikit-image</xref> </xrefs> <requirements> - <requirement type="package" version="6.1.0">pillow</requirement> - <requirement type="package" version="0.14.2">scikit-image</requirement> - <requirement type="package" version="1.15.4">numpy</requirement> - <requirement type="package" version="1.1.0">scipy</requirement> - <requirement type="package" version="0.15.1">tifffile</requirement> + <requirement type="package" version="@TOOL_VERSION@">scikit-image</requirement> + <requirement type="package" version="10.0.1">pillow</requirement> + <requirement type="package" version="1.24.4">numpy</requirement> + <requirement type="package" version="2021.7.2">tifffile</requirement> </requirements> - <command detect_errors="aggressive"> - <![CDATA[ - python '$__tool_directory__/scale_image.py' '$input' ./out.png - #if $use_scale_option.use_scale == 'true' - $use_scale_option.scale - #else if $use_scale_option.use_scale == 'false' - '[$use_scale_option.scale_x, $use_scale_option.scale_y]' - #end if - $order + <command detect_errors="aggressive"><![CDATA[ + + python '$__tool_directory__/scale_image.py' '$input' + + ./output.${input.ext} - ]]> - </command> + --scale '$scale' + --order $order + $antialias + + && mv ./output.${input.ext} ./output + + ]]></command> <inputs> <param name="input" type="data" format="png" label="Image file"/> - <conditional name="use_scale_option"><!--a third option (using one integer as percentage scaling) could still be implemented--> - <param label="Lock scaling between image dimensions" name="use_scale" type="select"> - <option selected="true" value="true">Lock</option> - <option value="false">Individual scales</option> - </param> - <when value="true"> - <param name="scale" type="float" value="1.0" label="Scaling factor" /> - </when> - <when value="false"> - <param name="scale_x" type="integer" value="100" label="New height of the image in pixels" /> - <param name="scale_y" type="integer" value="100" label="New width of the image in pixels" /> - </when> - </conditional> - <param name="order" type="select" label="Interpolation method"> + <param argument="--scale" type="text" value="1" label="Scaling factor" help="Use either a single scaling factor (uniform scaling), or a comma-separated list of scaling factors (anistropic scaling). For a 2-D single-channel or RGB image, the first scaling factor corresponds to the image width and the second corresponds to the image height. For images with 3 or more axes, the last axis is assumed to correspond to the image channels if uniform scaling is used (a single value)."/> + <param argument="--order" type="select" label="Interpolation method"> <option value="0">Nearest-neighbor</option> <option value="1" selected="true">Bi-linear</option> <option value="2">Bi-cubic</option> </param> + <param name="antialias" type="boolean" truevalue="--antialias" falsevalue="" checked="true" label="Enable anti-aliasing" help="This should only be used for down-scaling."/> </inputs> <outputs> - <data format="png" name="output" from_work_dir="out.png"/> + <data name="output" from_work_dir="output" format_source="input" metadata_source="input"/> </outputs> <tests> + <!-- Test PNG, without antialias --> <test> - <param name="input" value="sample1.png"/> <!--continue here--> - <conditional name="use_scale_option"> - <param name="use_scale" value="false"/> - <param name="scale_x" value="200"/> - <param name="scale_y" value="150"/> - </conditional> + <param name="input" value="input1_binary_rgb.png"/> + <param name="scale" value="0.5"/> + <param name="antialias" value="false"/> <param name="order" value="0"/> - <output name="output" value="out2.png" ftype="png" compare="sim_size"/> + <expand macro="tests/binary_image_diff" name="output" value="uniform_binary.png" ftype="png"/> + </test> + <!-- Test PNG, uniform scaling --> + <test> + <param name="input" value="input1_binary_rgb.png"/> + <param name="scale" value="0.5"/> + <expand macro="tests/intensity_image_diff" name="output" value="uniform.png" ftype="png"/> + </test> + <!-- Test PNG, anistropic scaling --> + <test> + <param name="input" value="input1_binary_rgb.png"/> + <param name="scale" value="0.5, 0.8"/> + <expand macro="tests/intensity_image_diff" name="output" value="anisotropic.png" ftype="png"/> + </test> + <test> + <param name="input" value="input1_binary_rgb.png"/> + <param name="scale" value="0.5, 0.8, 1"/> + <expand macro="tests/intensity_image_diff" name="output" value="anisotropic.png" ftype="png"/> + </test> + <!-- Test TIFF, normalized --> + <test> + <param name="input" value="input2_normalized.tiff"/> + <param name="scale" value="0.5"/> + <expand macro="tests/intensity_image_diff" name="output" value="normalized.tiff" ftype="tiff"/> + </test> + <!-- Test TIFF, not normalized --> + <test> + <param name="input" value="input3_not_normalized.tiff"/> + <param name="scale" value="0.5"/> + <expand macro="tests/intensity_image_diff" name="output" value="not_normalized.tiff" ftype="tiff"/> </test> </tests> <help> - **What it does** + + **Scales an image using one or more scaling factors.** - This tool scales an image using the scaling factor. + The image is rescaled uniformly along all axes, or anistropically if multiple scale factors are given. + + This operation preserves both the brightness of the image, and the range of values. + </help> <citations> <citation type="doi">10.1016/j.jbiotec.2017.07.019</citation>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests.xml Thu Apr 04 15:26:23 2024 +0000 @@ -0,0 +1,95 @@ +<macros> + + <!-- Macros for verification of image outputs --> + + <xml + name="tests/binary_image_diff" + tokens="name,value,ftype,metric,eps" + token_metric="mae" + token_eps="0.01"> + + <output name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@" pin_labels="0"> + <assert_contents> + <has_image_n_labels n="2"/> + <yield/> + </assert_contents> + </output> + + </xml> + + <xml + name="tests/label_image_diff" + tokens="name,value,ftype,metric,eps,pin_labels" + token_metric="iou" + token_eps="0.01" + token_pin_labels="0"> + + <output name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@" pin_labels="@PIN_LABELS@"> + <assert_contents> + <yield/> + </assert_contents> + </output> + + </xml> + + <xml + name="tests/intensity_image_diff" + tokens="name,value,ftype,metric,eps" + token_metric="rms" + token_eps="0.01"> + + <output name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@"> + <assert_contents> + <yield/> + </assert_contents> + </output> + + </xml> + + <!-- Variants of the above for verification of collection elements --> + + <xml + name="tests/binary_image_diff/element" + tokens="name,value,ftype,metric,eps" + token_metric="mae" + token_eps="0.01"> + + <element name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@" pin_labels="0"> + <assert_contents> + <has_image_n_labels n="2"/> + <yield/> + </assert_contents> + </element> + + </xml> + + <xml + name="tests/label_image_diff/element" + tokens="name,value,ftype,metric,eps" + token_metric="iou" + token_eps="0.01" + token_pin_labels="0"> + + <element name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@" pin_labels="@PIN_LABELS@"> + <assert_contents> + <yield/> + </assert_contents> + </element> + + </xml> + + <xml + name="tests/intensity_image_diff/element" + tokens="name,value,ftype,metric,eps" + token_metric="rms" + token_eps="0.01"> + + <element name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@"> + <assert_contents> + <yield/> + </assert_contents> + </element> + + </xml> + +</macros>