Implementation of diffusion filters (linear, nonlinear isotropic and nonlinear anisotropic)
Description
Implementation of diffusion filters - linear diffusion, nonlinear isotropic diffusion, and nonlinear anisotropic diffusion according to Weickert, Joachim. Anisotropic diffusion in image processing. Vol. 1. Stuttgart: Teubner, 1998.
Linear diffusion corresponds to a Gaussian filter and is present only for theoretical and consistency purposes.
Nonlinear isotropic diffusion contains an implementation of different diffusivity types: Perona-Malik, Charbonniere, exponential.
Nonlinear anisotropic diffusion has two modes ('eed', 'ced'), which correspond to Edge Enhancing Diffusion and Coherence Enhancing Diffusion.
All of the diffusion filters are computed by one of two schemes ('explicit', 'aos').
Checklist
- Docstrings for all functions
- Gallery example in
./doc/examples(new features only) - Benchmark in
./benchmarks, if your changes aren't covered by an existing benchmark - Unit tests
- Clean style in the spirit of PEP8
- Descriptive commit messages (see below)
For reviewers
- Check that the PR title is short, concise, and will make sense 1 year later.
- Check that new functions are imported in corresponding
__init__.py. - Check that new features, API changes, and deprecations are mentioned in
doc/release/release_dev.rst. - There is a bot to help automate backporting a PR to an older branch. For
example, to backport to v0.19.x after merging, add the following in a PR
comment:
@meeseeksdev backport to v0.19.x - To run benchmarks on a PR, add the
run-benchmarklabel. To rerun, the label can be removed and then added again. The benchmark output can be checked in the "Actions" tab.
Hello @AlexaKrnacova! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:
- In the file
skimage/filters/_diffusion_utils.py:
Line 3:80: E501 line too long (127 > 79 characters) Line 4:1: E302 expected 2 blank lines, found 1 Line 7:63: W504 line break after binary operator Line 8:17: E128 continuation line under-indented for visual indent Line 8:80: E501 line too long (115 > 79 characters) Line 8:115: W504 line break after binary operator Line 9:80: E501 line too long (111 > 79 characters) Line 9:111: W504 line break after binary operator Line 10:80: E501 line too long (115 > 79 characters) Line 10:115: W504 line break after binary operator Line 11:80: E501 line too long (103 > 79 characters) Line 11:103: W504 line break after binary operator Line 12:68: W504 line break after binary operator Line 13:80: E501 line too long (109 > 79 characters) Line 13:109: W504 line break after binary operator Line 14:80: E501 line too long (109 > 79 characters) Line 14:109: W504 line break after binary operator Line 15:80: E501 line too long (124 > 79 characters) Line 15:124: W504 line break after binary operator Line 16:80: E501 line too long (89 > 79 characters) Line 16:89: W504 line break after binary operator Line 17:80: E501 line too long (111 > 79 characters) Line 17:111: W504 line break after binary operator Line 18:80: E501 line too long (115 > 79 characters) Line 18:115: W504 line break after binary operator Line 19:80: E501 line too long (111 > 79 characters) Line 19:111: W504 line break after binary operator Line 20:80: E501 line too long (98 > 79 characters) Line 23:80: E501 line too long (117 > 79 characters) Line 29:80: E501 line too long (113 > 79 characters) Line 29:113: W504 line break after binary operator Line 30:21: E128 continuation line under-indented for visual indent Line 31:25: E127 continuation line over-indented for visual indent Line 31:80: E501 line too long (107 > 79 characters) Line 31:107: W504 line break after binary operator Line 32:25: E128 continuation line under-indented for visual indent Line 32:80: E501 line too long (148 > 79 characters) Line 32:148: W504 line break after binary operator Line 33:25: E128 continuation line under-indented for visual indent Line 33:80: E501 line too long (148 > 79 characters) Line 33:148: W504 line break after binary operator Line 34:25: E128 continuation line under-indented for visual indent Line 34:80: E501 line too long (153 > 79 characters) Line 34:153: W504 line break after binary operator Line 35:25: E128 continuation line under-indented for visual indent Line 35:80: E501 line too long (130 > 79 characters) Line 35:130: W504 line break after binary operator Line 36:25: E128 continuation line under-indented for visual indent Line 36:80: E501 line too long (130 > 79 characters) Line 36:130: W504 line break after binary operator Line 37:25: E128 continuation line under-indented for visual indent Line 37:80: E501 line too long (166 > 79 characters) Line 46:21: E128 continuation line under-indented for visual indent Line 47:21: E126 continuation line over-indented for hanging indent Line 70:52: W504 line break after binary operator Line 78:56: W504 line break after binary operator Line 143:48: W504 line break after binary operator Line 144:72: W504 line break after binary operator Line 145:48: W504 line break after binary operator Line 146:72: W504 line break after binary operator Line 147:48: W504 line break after binary operator Line 148:72: W504 line break after binary operator Line 149:48: W504 line break after binary operator Line 174:27: W504 line break after binary operator Line 207:80: E501 line too long (101 > 79 characters) Line 218:26: W504 line break after binary operator Line 221:20: W504 line break after binary operator Line 225:34: W504 line break after binary operator
- In the file
skimage/filters/diffusion_linear.py:
Line 60:80: E501 line too long (100 > 79 characters)
- In the file
skimage/filters/diffusion_nonlinear_aniso.py:
Line 84:80: E501 line too long (87 > 79 characters) Line 87:80: E501 line too long (151 > 79 characters) Line 91:80: E501 line too long (144 > 79 characters) Line 111:1: W293 blank line contains whitespace Line 140:13: E126 continuation line over-indented for hanging indent Line 218:17: E126 continuation line over-indented for hanging indent Line 242:17: E126 continuation line over-indented for hanging indent
- In the file
skimage/filters/diffusion_nonlinear_iso.py:
Line 69:80: E501 line too long (83 > 79 characters) Line 70:80: E501 line too long (127 > 79 characters) Line 114:80: E501 line too long (80 > 79 characters) Line 115:34: E128 continuation line under-indented for visual indent Line 129:36: E128 continuation line under-indented for visual indent
- In the file
skimage/filters/tests/test_diffusion.py:
Line 35:19: E226 missing whitespace around arithmetic operator
Comment last updated at 2022-05-17 19:10:18 UTC
Thanks for contributing this @AlexaKrnacova! These do seem like popular methods that would be nice to have.
I did not get a chance to take a close look yet, but saw that you were using Numba jit to accelerate some functions. Since Numba is a pretty heavy dependency (it relies on LLVM), we do not currently use it in scikit-image. I think you can likely get a similar speedup for these functions using Pythran or Cython, both of which we currently use.
Once you are sure the pure Python code is working as expected, then we can worry about how to accelerate things. I would try Pythran first as you may not require any changes other than adding some annotation at the top of these functions such as the one here. Aside from the annotation, likely the only other needed change would be listing the pythran file in the setup.py as in the example here.
Thanks, @grlee77! It's my first time contributing, but I hope it will be successful. I saw that numba is used in the code, so I got confused, but I will look into Pythran.
Also, I feel like this PR is ready for review, except for Benchmarks - I'm not quite sure what to do with it. There are some unresolved flake8 warnings, but they are mainly because of large equations in diffusion_utils that cannot be transformed into a way flake8 is satisfied.
Thanks for the contribution @AlexaKrnacova!
I think it would be good to describe in the example why these filters are useful. They seem like blurring operators, but why use these rather than Gaussian (or linear diffusion)?
Is this specifically for 2D data, or can it be applied to volumes in general? I saw in the gradient calculation X, Y, Z being mentioned.
Thank you, @stefanv!
Nonlinear diffusion filters are good for preserving edges. Each filter has an individual effect on an image. Isotropic diffusion smoothes the image in homogenous sections of an image and weakens the blurring effect near edges. Therefore, noise at the edges cannot be eliminated successfully by this process. This problem can be solved by using an anisotropic diffusion filter - Edge Enhancing Diffusion (EED). Diffusivity is chosen to be tensor (matrix 2x2) instead of scalar like in isotropic and linear diffusion. The diffusion tensor controls the diffusion flux. The last implemented filter is Coherence Enhancing Diffusion (CED) - also part of the anisotropic diffusion. This filter enhances flow-like structures in an image and fills out interrupted (noisy) lines.
More information about diffusion can be found in this book by Weickert. Filters and results of each filter can be seen in doc/examples/filters/plot_diffusion_filters.py.
These filters are only for 2D data right now but they can be extended to 3D.
Hey, there hasn't been any activity on this pull request for more than 180 days. For now, we have marked it as "dormant" until there is some new activity. You are welcome to reach out to people by mentioning them here or on our forum if you need more feedback! Otherwise, we would be thankful for a short update, for example if you would like to continue or if you are okay with someone else doing so. In any case, thank you for your contributions so far!