Skip to content

Commit

Permalink
Update scale_image tool (not finished yet)
Browse files Browse the repository at this point in the history
  • Loading branch information
kostrykin committed Mar 19, 2024
1 parent affd76b commit 493adf4
Show file tree
Hide file tree
Showing 16 changed files with 118 additions and 63 deletions.
12 changes: 10 additions & 2 deletions macros/tests.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
token_metric="iou"
token_eps="0.01">

<output name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@"/>
<output name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@">
<assert_contents>
<yield/>
</assert_contents>
</output>

</xml>

Expand All @@ -31,7 +35,11 @@
token_metric="rms"
token_eps="0.01">

<output name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@"/>
<output name="@NAME@" value="@VALUE@" ftype="@FTYPE@" compare="image_diff" metric="@METRIC@" eps="@EPS@">
<assert_contents>
<yield/>
</assert_contents>
</output>

</xml>

Expand Down
3 changes: 3 additions & 0 deletions tools/2d_simple_filter/filter.xml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@

**Applies a standard filter to a single-channel 2-D image.**

Note that this operation can change the range of the values of the image intensities in the image.
This is necessary, for example, to preserve the brightness of the image after filtering.

</help>
<citations>
<citation type="doi">10.1016/j.jbiotec.2017.07.019</citation>
Expand Down
1 change: 1 addition & 0 deletions tools/scale_image/creators.xml
52 changes: 32 additions & 20 deletions tools/scale_image/scale_image.py
Original file line number Diff line number Diff line change
@@ -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(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 = int(scale)
res = scipy.misc.imresize(img_in, scale, interp=interp)
scale = float(scale)

# Do the scaling
res = skimage.transform.rescale(im, scale, order, anti_aliasing=antialias)

# Convert `res` to the same dtype as `im`,
# it is important to preserve the dtype so that both brightness and range of values is preserved
if res.dtype != im.dtype:
src_max_value = skimage.util.dtype_limits(res)[1]
dst_max_value = skimage.util.dtype_limits(im)[1]
res = (res / src_max_value) * dst_max_value
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)
112 changes: 71 additions & 41 deletions tools/scale_image/scale_image.xml
Original file line number Diff line number Diff line change
@@ -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>
Expand All @@ -8,64 +17,85 @@
<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[
]]>
</command>
python '$__tool_directory__/scale_image.py' '$input'
./output.${input.ext}
--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."/>
<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 format="png" name="output" from_work_dir="output"/>
</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"/>
<output name="output" value="normalized.tiff" ftype="tiff" compare="sim_size" delta_frac="0.01"/><!-- Looks like pillow cannot read float TIFFs -->
</test>
<!-- Test TIFF, not normalized -->
<test>
<param name="input" value="input3_not_normalized.tiff"/>
<param name="scale" value="0.5"/>
<output name="output" value="not_normalized.tiff" ftype="tiff" compare="sim_size" delta_frac="0.01"/><!-- Looks like pillow cannot read float TIFFs -->
</test>
</tests>
<help>
**What it does**

This tool scales an image using the scaling factor.
**Scales an image using one or more scaling factors.**

The image is rescaled uniformly along all axes, or anistropically if multiple scale factors are given.

Note that this operation can change the range of the values of the image intensities in the image.
This is necessary, for example, to preserve the brightness of the image after scaling.

</help>
<citations>
<citation type="doi">10.1016/j.jbiotec.2017.07.019</citation>
Expand Down
Binary file added tools/scale_image/test-data/anisotropic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tools/scale_image/test-data/input1_binary_rgb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file added tools/scale_image/test-data/normalized.tiff
Binary file not shown.
Binary file added tools/scale_image/test-data/not_normalized.tiff
Binary file not shown.
Binary file removed tools/scale_image/test-data/out.png
Binary file not shown.
Binary file removed tools/scale_image/test-data/out2.png
Binary file not shown.
Binary file removed tools/scale_image/test-data/sample1.png
Binary file not shown.
Binary file added tools/scale_image/test-data/uniform_binary.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions tools/scale_image/tests.xml

0 comments on commit 493adf4

Please sign in to comment.