Comments (7)
This issue has been mentioned on Image.sc Forum. There might be relevant details there:
from scikit-image.
[...] the implementation may discard the imaginary part of a complex PSF, focusing only on the real component (
psf = psf.real.astype(float_type, copy=False)
). This approach could potentially omit critical phase information inherent in the imaginary part, which might be essential for accurate deconvolution. [...]
As stated in my comment, Iβm not really familiar with that function but after some Git sleuthing it looks like it might have been an oversight that was introduced in single precision support in skimage.restoration module #5219. I havenβt checked the PR and context in detail though.
It seems like instead of always casting the real part to float_type it should check if reg and psf are complex and then use the corresponding complex type instead. E.g. float32
β complex64
β¦
Code snippet for investigation
Not sure if this actually makes sense in practice actually!
import skimage as ski
import scipy as sp
import numpy as np
img = ski.color.rgb2gray(ski.data.astronaut())
psf = np.ones((5, 5)) / 25
img = sp.signal.convolve2d(img, psf, 'same')
rng = np.random.default_rng()
img += 0.1 * img.std() * rng.standard_normal(img.shape)
psf = psf * (1+1j)
deconvolved_img = ski.restoration.wiener(img, psf, 0.1)
from scikit-image.
Optimistically pinging @jni, @grlee77 and @FirefoxMetzger in the hope they have a deeper understanding of this and some quick insights into the potential bug. π
from scikit-image.
This issue has been mentioned on Image.sc Forum. There might be relevant details there:
from scikit-image.
It appears that the issue can be addressed by making the following two modifications:
-
Comment out the following two lines:
# psf = psf.real.astype(float_type, copy=False) # reg = reg.real.astype(float_type, copy=False)
-
Modify this line:
if is_real: deconv = uft.uirfftn(wiener_filter * uft.urfftn(image), shape=image.shape) else: deconv = uft.uifftn(wiener_filter * uft.ufftn(image))
to:
if not is_real: deconv = np.real(uft.uifftn(wiener_filter * uft.ufftn(image))) else: deconv = uft.uirfftn(wiener_filter * uft.urfftn(image), shape=image.shape)
The second modification includes logical clarification.
from scikit-image.
I've identified another potential bug. When the "psf" (Point Spread Function) is provided with the same shape as the "image", it's directly passed to "trans_func" without being transformed by "ir2tf":
if psf.shape != reg.shape:
trans_func = uft.ir2tf(psf, image.shape, is_real=is_real)
else:
trans_func = psf
To ensure that the "psf" is always correctly transformed, regardless of its shape, I suggest modifying the condition to check if the "psf" is a complex object. If it's not, it should be transformed using "ir2tf". Here's the proposed change:
if not np.iscomplexobj(psf):
trans_func = uft.ir2tf(psf, image.shape, is_real=is_real)
else:
trans_func = psf
This change ensures that the "psf" is always in the correct format for processing, whether it initially matches the "image" shape or not.
from scikit-image.
Below is the "git diff" highlighting the minimal changes needed. From my testing, these modifications work well for my specific use cases.
--- a/skimage/restoration/deconvolution.py
+++ b/skimage/restoration/deconvolution.py
@@ -116,10 +116,8 @@ def wiener(image, psf, balance, reg=None, is_real=True, clip=True):
reg = uft.ir2tf(reg, image.shape, is_real=is_real)
float_type = _supported_float_type(image.dtype)
image = image.astype(float_type, copy=False)
- psf = psf.real.astype(float_type, copy=False)
- reg = reg.real.astype(float_type, copy=False)
- if psf.shape != reg.shape:
+ if not np.iscomplexobj(psf):
trans_func = uft.ir2tf(psf, image.shape, is_real=is_real)
else:
trans_func = psf
@@ -130,7 +128,7 @@ def wiener(image, psf, balance, reg=None, is_real=True, clip=True):
deconv = uft.uirfftn(wiener_filter * uft.urfftn(image),
shape=image.shape)
else:
- deconv = uft.uifftn(wiener_filter * uft.ufftn(image))
+ deconv = np.real(uft.uifftn(wiener_filter * uft.ufftn(image)))
if clip:
deconv[deconv > 1] = 1
from scikit-image.
Related Issues (20)
- Collections attribute is used in gallery but was deprecated in Matplotlib 3.8. HOT 1
- Feature smaller, focused gallery examples with a lower priority
- 0.23 release HOT 10
- Cannot catch MemoryError
- A typo in source code comment and document HOT 2
- io.imread() not opening renamed NDTiffStacks HOT 4
- Wheel building action fails with `actions/upload-artifact@v4` HOT 1
- In `scikit-image==0.23.1` `img_as_ubyte` stop accepting `np.ulonglong` HOT 22
- Investigate performance optimization in `_corner_fast` HOT 2
- test_unsharp_masking_output_type_and_shape fails on non-x86 architectures HOT 9
- H&E and Residual, rather than HED HOT 5
- Invalid no-name-in-module from pylint on scikit-image>=0.19.0 using filters module HOT 3
- libatlas 3.10.3 related failures on debian
- Discrepancy of skimage.filters.frangi output between 0.19.3 and 0.22.0 HOT 2
- Adding `spacing` to `extra_properties`'s possible arguments in `regionprops` HOT 3
- CI fails on MacOS with "clang cannot compile programs" HOT 2
- ORB test points file should be read in x-y and not r-c
- Typo in `skimage.measure.find_contours` HOT 3
- Vulnerability: code injection HOT 9
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from scikit-image.