Repository: scikit-image/scikit-image

Issue:
restoration.wiener doc example gives poor result
## Description
I had a look at the [Example code](https://scikit-image.org/docs/dev/api/skimage.restoration.html#skimage.restoration.wiener) for Wiener-Hunt deconvolution and the result I get looks blurrier than the image it starts with. Is this the expected behavior? I played around with the balance parameter but it didn't help. I am trying to understand if this is the deconvolution that would be applicable to my problem.


![wiener](https://user-images.githubusercontent.com/30300213/140739161-dd23c663-be90-428b-bbbf-c4c948726146.png)

<!--

(Note: for guidance on how to use `scikit-image`, please post instead on https://forum.image.sc/tag/scikit-image)
-->

## Way to reproduce
```python
from skimage import color, data, restoration
img = color.rgb2gray(data.astronaut())
from scipy.signal import convolve2d
psf = np.ones((5, 5)) / 25
conv = convolve2d(img, psf, 'same')
rng = np.random.default_rng()
noised = conv + 0.1 * conv.std() * rng.standard_normal(conv.shape)
deconvolved_img = restoration.wiener(noised, psf, 1100)


fig, ax = plt.subplots(nrows=1, ncols=4, figsize=(8, 6))
plt.gray()


ax[0].imshow(img)
ax[0].set_title('Original')
ax[0].axis('off')

ax[1].imshow(conv)
ax[1].set_title('Convoluted')
ax[1].axis('off')

ax[2].imshow(noised)
ax[2].set_title('Noised')
ax[2].axis('off')

ax[3].imshow(deconvolved_img)
ax[3].set_title('Restoration using Wiener')
ax[3].axis('off')

fig.subplots_adjust(wspace=0.02, hspace=0.2,
                    top=0.9, bottom=0.05, left=0, right=1)
plt.show()
```


## Version information

```python
3.9.7 (default, Sep 16 2021, 13:09:58) 
[GCC 7.5.0]
Linux-3.10.0-1160.36.2.el7.x86_64-x86_64-with-glibc2.17
scikit-image version: 0.18.1
numpy version: 1.21.2

```



Discussion:
Thanks for reporting this @elena-pascal. I can reproduce the same issue on the current development branch as well.

I think the problem is in the value of 1100 in this line:
> deconvolved_img = restoration.wiener(noised, psf, 1100)

I think at some point this function must have changed how the data was rescaled internally and the value of 1100 for `balance` here is no longer reasonable. If this is changed to a much smaller value of around 1.0 it looks much less blurred. Will have to investigate a bit to see how far back this change occurred and what the equivalent value is for the current implementation.
Oh I see. The [test ](https://github.com/scikit-image/scikit-image/blob/main/skimage/restoration/tests/test_restoration.py#L36) is also written for a `balance` value of 0.05 at that indeed looks right. It makes sense why I didn't have any luck playing around with that parameter, I didn't go low enough. How are the optimal values for `balance` determined btw?
I'm happy to try and update the docs with the 0.05 value and perhaps output image if the consistency search agrees with this value.
Dear @elena-pascal (and @grlee77 :wink:),

Looking at the [history](https://github.com/scikit-image/scikit-image/blame/main/skimage/restoration/deconvolution.py), I don't think that `balance=1100` in `deconvolved_img = restoration.wiener(img, psf, 1100)` was ever suitable with `img` deriving from `color.rgb2gray(data.astronaut())`. Maybe this value once worked with `data.lena()` (see https://github.com/scikit-image/scikit-image/commit/1b217f971e9682dacb8adf7715e18175c9e40fc7#diff-87be2b5ca31afe4ca1d683cb77680447282dc3a265e6620d4661669a9b546b4a)? I wouldn't even think so, since converting the image with `color.rgb2gray` would bring its values in the 0 to 1 range.

I guess this was simply never caught because there is neither a visual check (as in plotting, like you've done) nor a quantitative test (as in `test_wiener`, that you've linked to).

Indeed, the only recent changes that this function and its docstring have undergone recently (a few months ago vs. 7 or 8 years ago) are:

* the update of `numpy.random.x` and
* the addition of single-precision float type support.

Neither change can account for a value of `balance=1100` which would work before and not anymore.

So, I would say, please go ahead and update the docstring! To determine an optimal `balance` value, maybe you could run the newly implemented [blur metric](https://scikit-image.org/docs/dev/api/skimage.measure.html?highlight=blur#skimage.measure.blur_effect) on the output, and pick the best? This should also match what you're perceiving with your eyes... :eyes: :slightly_smiling_face: 

Thanks again for reporting!

PS: This link https://pro.orieux.fr/files/papers/OGR-JOSA10.pdf (provided in the references) is now broken. :slightly_frowning_face: 

Resolving patch:
diff --git a/doc/examples/filters/plot_restoration.py b/doc/examples/filters/plot_restoration.py
--- a/doc/examples/filters/plot_restoration.py
+++ b/doc/examples/filters/plot_restoration.py
@@ -4,22 +4,22 @@
 =====================
 
 In this example, we deconvolve a noisy version of an image using Wiener
-and unsupervised Wiener algorithms. This algorithms are based on
+and unsupervised Wiener algorithms. These algorithms are based on
 linear models that can't restore sharp edge as much as non-linear
 methods (like TV restoration) but are much faster.
 
 Wiener filter
 -------------
 The inverse filter based on the PSF (Point Spread Function),
-the prior regularisation (penalisation of high frequency) and the
+the prior regularization (penalisation of high frequency) and the
 tradeoff between the data and prior adequacy. The regularization
 parameter must be hand tuned.
 
 Unsupervised Wiener
 -------------------
-This algorithm has a self-tuned regularisation parameters based on
+This algorithm has a self-tuned regularization parameters based on
 data learning. This is not common and based on the following
-publication [1]_. The algorithm is based on a iterative Gibbs sampler that
+publication [1]_. The algorithm is based on an iterative Gibbs sampler that
 draw alternatively samples of posterior conditional law of the image,
 the noise power and the image frequency power.
 
@@ -27,6 +27,8 @@
        Rodet, "Bayesian estimation of regularization and point
        spread function parameters for Wiener-Hunt deconvolution",
        J. Opt. Soc. Am. A 27, 1593-1607 (2010)
+       https://www.osapublishing.org/josaa/abstract.cfm?URI=josaa-27-7-1593
+       https://hal.archives-ouvertes.fr/hal-00674508
 """
 import numpy as np
 import matplotlib.pyplot as plt
diff --git a/skimage/restoration/deconvolution.py b/skimage/restoration/deconvolution.py
--- a/skimage/restoration/deconvolution.py
+++ b/skimage/restoration/deconvolution.py
@@ -60,7 +60,7 @@ def wiener(image, psf, balance, reg=None, is_real=True, clip=True):
     >>> img = convolve2d(img, psf, 'same')
     >>> rng = np.random.default_rng()
     >>> img += 0.1 * img.std() * rng.standard_normal(img.shape)
-    >>> deconvolved_img = restoration.wiener(img, psf, 1100)
+    >>> deconvolved_img = restoration.wiener(img, psf, 0.1)
 
     Notes
     -----
@@ -86,7 +86,7 @@ def wiener(image, psf, balance, reg=None, is_real=True, clip=True):
     those coming from noise), and the regularization.
 
     These methods are then specific to a prior model. Consequently,
-    the application or the true image nature must corresponds to the
+    the application or the true image nature must correspond to the
     prior model. By default, the prior model (Laplacian) introduce
     image smoothness or pixel correlation. It can also be interpreted
     as high-frequency penalization to compensate the instability of
@@ -94,7 +94,7 @@ def wiener(image, psf, balance, reg=None, is_real=True, clip=True):
     amplification or "explosive" solution).
 
     Finally, the use of Fourier space implies a circulant property of
-    :math:`H`, see [Hunt].
+    :math:`H`, see [2]_.
 
     References
     ----------
@@ -105,7 +105,7 @@ def wiener(image, psf, balance, reg=None, is_real=True, clip=True):
 
            https://www.osapublishing.org/josaa/abstract.cfm?URI=josaa-27-7-1593
 
-           http://research.orieux.fr/files/papers/OGR-JOSA10.pdf
+           https://hal.archives-ouvertes.fr/hal-00674508
 
     .. [2] B. R. Hunt "A matrix theory proof of the discrete
            convolution theorem", IEEE Trans. on Audio and
@@ -228,7 +228,7 @@ def unsupervised_wiener(image, psf, reg=None, user_params=None, is_real=True,
     posterior law. The practical idea is to only draw highly probable
     images since they have the biggest contribution to the mean. At the
     opposite, the less probable images are drawn less often since
-    their contribution is low. Finally the empirical mean of these
+    their contribution is low. Finally, the empirical mean of these
     samples give us an estimation of the mean, and an exact
     computation with an infinite sample set.
 
@@ -241,7 +241,7 @@ def unsupervised_wiener(image, psf, reg=None, user_params=None, is_real=True,
 
            https://www.osapublishing.org/josaa/abstract.cfm?URI=josaa-27-7-1593
 
-           http://research.orieux.fr/files/papers/OGR-JOSA10.pdf
+           https://hal.archives-ouvertes.fr/hal-00674508
     """
 
     if user_params is not None:


Test patch: