-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add morphological_operations
tool
#106
Merged
bgruening
merged 4 commits into
BMCV:master
from
kostrykin:add-morphology-tools/upstream
Mar 8, 2024
Merged
Changes from 1 commit
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"image":"mcr.microsoft.com/devcontainers/universal:2", | ||
"customizations": { | ||
"vscode": { | ||
"extensions": [ | ||
"davelopez.galaxy-tools", | ||
"ms-python.flake8" | ||
] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
categories: | ||
- Imaging | ||
description: Apply morphological operations to images | ||
long_description: Apply morphological operations to images. | ||
name: morphological_operations | ||
owner: imgteam | ||
homepage_url: https://github.com/bmcv | ||
remote_repository_url: https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/morphological_operations |
93 changes: 93 additions & 0 deletions
93
tools/morphological_operations/morphological_operations.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
133 changes: 133 additions & 0 deletions
133
tools/morphological_operations/morphological_operations.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
<tool id="morphological_operations" name="Apply a morphological operation" version="@TOOL_VERSION@+galaxy@VERSION_SUFFIX@" profile="23.0"> | ||
<description>with SciPy</description> | ||
<macros> | ||
<token name="@TOOL_VERSION@">1.12.0</token> | ||
<token name="@VERSION_SUFFIX@">0</token> | ||
</macros> | ||
<edam_operations> | ||
<edam_operation>operation_3443</edam_operation> | ||
</edam_operations> | ||
<xrefs> | ||
<xref type="biii">scipy</xref> | ||
</xrefs> | ||
<requirements> | ||
<requirement type="package" version="1.12.0">scipy</requirement> | ||
<requirement type="package" version="0.22.0">scikit-image</requirement> | ||
</requirements> | ||
<command><![CDATA[ | ||
|
||
## Inputs | ||
|
||
python '$__tool_directory__/morphological_operations.py' '$image' | ||
--operation $operation | ||
--selem-shape $selem_shape | ||
--selem-size $selem_size | ||
|
||
## Outputs | ||
|
||
./result.tiff | ||
|
||
]]> | ||
</command> | ||
<inputs> | ||
<param name="image" type="data" format="png,tiff" label="Input image" /> | ||
<param label="Morphological operation" argument="--operation" type="select"> | ||
<option value="erosion" selected="True">Erosion</option> | ||
<option value="dilation">Dilation</option> | ||
<option value="opening">Opening</option> | ||
<option value="closing">Closing</option> | ||
<option value="fill_holes">Fill holes</option> | ||
</param> | ||
<param label="Structuring element" argument="--selem-shape" type="select"> | ||
<option value="disk" selected="True">Disk</option> | ||
<option value="square">Square</option> | ||
</param> | ||
<param label="Structuring element size" argument="--selem-size" type="integer" min="1" max="256" value="1" help="The radius of the disk, or the width of the square, in pixels." /> | ||
</inputs> | ||
<outputs> | ||
<data format="tiff" name="result" from_work_dir="result.tiff" /> | ||
</outputs> | ||
<tests> | ||
<!-- Test binary operations (input images with two distinct values) --> | ||
<test> | ||
<param name="image" value="input1.tiff" /> | ||
<param name="operation" value="erosion" /> | ||
<param name="selem_shape" value="disk" /> | ||
<param name="selem_size" value="1" /> | ||
<output name="result" value="output1_erosion.tiff" ftype="tiff" compare="sim_size" delta="10" /> | ||
</test> | ||
<test> | ||
<param name="image" value="input1.tiff" /> | ||
<param name="operation" value="dilation" /> | ||
<param name="selem_shape" value="disk" /> | ||
<param name="selem_size" value="2" /> | ||
<output name="result" value="output1_dilation.tiff" ftype="tiff" compare="sim_size" delta="10" /> | ||
</test> | ||
<test> | ||
<param name="image" value="input1.tiff" /> | ||
<param name="operation" value="opening" /> | ||
<param name="selem_shape" value="square" /> | ||
<param name="selem_size" value="1" /> | ||
<output name="result" value="output1_opening.tiff" ftype="tiff" compare="sim_size" delta="10" /> | ||
</test> | ||
<test> | ||
<param name="image" value="input1.tiff" /> | ||
<param name="operation" value="closing" /> | ||
<param name="selem_shape" value="square" /> | ||
<param name="selem_size" value="2" /> | ||
<output name="result" value="output1_closing.tiff" ftype="tiff" compare="sim_size" delta="10" /> | ||
</test> | ||
<!-- Test intensity-based operations (more than two distinct values) --> | ||
<test> | ||
<param name="image" value="input3.png" /> | ||
<param name="operation" value="erosion" /> | ||
<param name="selem_shape" value="disk" /> | ||
<param name="selem_size" value="1" /> | ||
<output name="result" value="output3_erosion.tiff" ftype="tiff" compare="sim_size" delta="10" /> | ||
</test> | ||
<test> | ||
<param name="image" value="input3.png" /> | ||
<param name="operation" value="dilation" /> | ||
<param name="selem_shape" value="disk" /> | ||
<param name="selem_size" value="2" /> | ||
<output name="result" value="output3_dilation.tiff" ftype="tiff" compare="sim_size" delta="10" /> | ||
</test> | ||
<test> | ||
<param name="image" value="input3.png" /> | ||
<param name="operation" value="opening" /> | ||
<param name="selem_shape" value="square" /> | ||
<param name="selem_size" value="1" /> | ||
<output name="result" value="output3_opening.tiff" ftype="tiff" compare="sim_size" delta="10" /> | ||
</test> | ||
<test> | ||
<param name="image" value="input3.png" /> | ||
<param name="operation" value="closing" /> | ||
<param name="selem_shape" value="square" /> | ||
<param name="selem_size" value="2" /> | ||
<output name="result" value="output3_closing.tiff" ftype="tiff" compare="sim_size" delta="10" /> | ||
</test> | ||
<!-- Test multi-channel image (with two distinct values per channel) --> | ||
<test> | ||
<param name="image" value="input2.png" /> | ||
<param name="operation" value="fill_holes" /> | ||
<param name="selem_shape" value="disk" /> | ||
<param name="selem_size" value="1" /> | ||
<output name="result" value="output2_fill_holes.tiff" ftype="tiff" compare="sim_size" delta="10" /> | ||
</test> | ||
</tests> | ||
<help> | ||
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. | ||
</help> | ||
<citations> | ||
<citation type="doi">10.1038/s41592-019-0686-2</citation> | ||
</citations> | ||
</tool> |
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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 not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one should be removed and added to the gitignore file I think.