As Context-Adaptive Interpolator is slow and possibly incorrectly implemented, let us try a good known working denoiser:
importmatplotlib.pyplotaspltfromskimage.restorationimport(denoise_tv_chambolle,denoise_bilateral,denoise_wavelet,estimate_sigma)fromskimageimportdata,img_as_floatfromskimage.utilimportrandom_noiseoriginal=img_as_float(data.chelsea()[100:250,50:300])sigma=0.155noisy=random_noise(original,var=sigma**2)fig,ax=plt.subplots(nrows=2,ncols=4,figsize=(8,5),sharex=True,sharey=True)plt.gray()# Estimate the average noise standard deviation across color channels.sigma_est=estimate_sigma(noisy,channel_axis=-1,average_sigmas=True)# Due to clipping in random_noise, the estimate will be a bit smaller than the# specified sigma.print(f'Estimated Gaussian noise standard deviation = {sigma_est}')tiles=[{'title':'Original','image':original,},{'title':'Noisy','image':noisy,},{'title':'TV','image':denoise_tv_chambolle(noisy,weight=0.1,channel_axis=-1),},{'title':'(more) TV','image':denoise_tv_chambolle(noisy,weight=0.2,channel_axis=-1),},{'title':'Bilateral','image':denoise_bilateral(noisy,sigma_color=0.05,sigma_spatial=15,channel_axis=-1),},{'title':'(more) Bilateral','image':denoise_bilateral(noisy,sigma_color=0.1,sigma_spatial=15,channel_axis=-1),},{'title':'Wavelet denoising','image':denoise_wavelet(noisy,channel_axis=-1,rescale_sigma=True),},{'title':'Wavelet denoising\nin YCbCr colorspace','image':denoise_wavelet(noisy,channel_axis=-1,convert2ycbcr=True,rescale_sigma=True),},]foryinrange(2):forxinrange(4):axis=ax[y,x]tile=tiles[y*4+x]axis.imshow(tile['image'])axis.axis('off')rms=rmsDiffNumpy(tile['image'],original)axis.set_title(tile['title']+f'\nRMS with original: {round(rms,4)}')fig.tight_layout()plt.show()
PRNU quite guessable on a given image. Now need to reduce its factor and mean on several images to make it clear.
With PRNU_FACTOR = 0.01 it is more subtile but still visible on both images. For the image with PRNU see the U. For the PRNU estimate look at the top of R and bottom of U for instance.
PRNU estimate taking into account all images:
Manipulating brightness and contrast on GIMP does not enable a clear result as the following one. However, the not significant RMS decreasing reason is unclear. Even with normalizing it does not seem to make sense.
With `PRNU_FACTOR = 0.1`:
`PRNU` quite guessable on a given image. Now need to reduce its factor and mean on several images to make it clear.


With `PRNU_FACTOR = 0.01` it is more subtile but still visible on both images. For the image with PRNU see the `U`. For the PRNU estimate look at the top of `R` and bottom of `U` for instance.



PRNU estimate taking into account all images:

Manipulating brightness and contrast on GIMP does not enable a clear result as the following one. However, the not significant RMS decreasing reason is unclear. Even with normalizing it does not seem to make sense.
In a first time we show an example of Gaussian noise and PRNU on an image, then we consider the PRNU estimate on the mean of the extracted noise for the considered images: in a first time only full images and in a second time split each images in 4x4.
With NOISE_FACTOR = 0.25:
With NOISE_FACTOR = 0.1:
In a first time we show an example of Gaussian noise and PRNU on an image, then we consider the PRNU estimate on the mean of the extracted noise for the considered images: in a first time only full images and in a second time split each images in 4x4.
With `NOISE_FACTOR = 0.25`:



With `NOISE_FACTOR = 0.1`:



If want to move on Gaussian noise as PRNU, then have to understand RMS unexpected results. May also be surprised, so can try anyway. To have recognizable PRNU can use GIMP > Filters > Noise > RGB Noise... selecting white and setting {Red,Blue,Green} to 1.
If want to move on Gaussian noise as PRNU, then have to understand RMS unexpected results. May also be surprised, so can try anyway. To have recognizable PRNU can use `GIMP` > `Filters` > `Noise` > `RGB Noise...` selecting white and setting `{Red,Blue,Green}` to `1`.




Concerning the RMS, maybe it is due to residual scene and with more images we would have a many pixels, hence important, less significant as nearer to 0.
Concerning the RMS, maybe it is due to residual scene and with more images we would have a many pixels, hence important, less significant as nearer to 0.
How to ease visualizing the values of this rendering of image of floats? Could render as a greyscale image to make sure of my rough understanding of image values.
How to ease visualizing the values of this rendering of image of floats? Could render as a greyscale image to make sure of my rough understanding of image values.
I start having the feeling that the RMS inconsistency is because of the PRNU estimation background which can not converge to 0 as it is just adding residual scene.
I start having the feeling that the RMS inconsistency is because of the PRNU estimation background which can not converge to 0 as it is just adding residual scene.

The associated code is at https://gitea.lemnoslife.com/Benjamin_Loison/Robust_image_source_identification_on_modern_smartphones/src/commit/dd7a6892e50a6fb4ef9142028d9b25ab835e6598/datasets/noise_free_test_images/estimate_prnu.py.
/home/benjamin/.local/lib/python3.10/site-packages/matplotlib/projections/__init__.py:63: UserWarning: Unable to import Axes3D. This may be due to multiple versions of Matplotlib being installed (e.g. as a system package and as a pip package). As a result, the 3D projection is not available.
warnings.warn("Unable to import Axes3D. This may be due to multiple versions of "
Traceback (most recent call last):
File "<tmp 1>", line 14, in <module>
cax = divider.append_axes('right', size='5%', pad=0.05)
File "/home/benjamin/.local/lib/python3.10/site-packages/matplotlib/_api/deprecation.py", line 387, in wrapper
return func(*inner_args, **inner_kwargs)
File "/usr/lib/python3/dist-packages/mpl_toolkits/axes_grid1/axes_divider.py", line 552, in append_axes
ax = self.new_horizontal(size, pad, pack_start=False, **kwargs)
File "/usr/lib/python3/dist-packages/mpl_toolkits/axes_grid1/axes_divider.py", line 486, in new_horizontal
ax = self._get_new_axes(**kwargs)
File "/usr/lib/python3/dist-packages/mpl_toolkits/axes_grid1/axes_divider.py", line 437, in _get_new_axes
axes_class = axes._axes_class
AttributeError: 'Axes' object has no attribute '_axes_class'
Traceback (most recent call last):
File "<tmp 2>", line 162, in <module>
plt.register_cmap(cmap=blue_red2)
AttributeError: module 'matplotlib.pyplot' has no attribute 'register_cmap'
The other answers to the mentioned Stack Overflow question do not seem interesting.
orientation = 'horizontal' makes the figure ok.
Add a single or multiple color scales?
Related to [Benjamin_Loison/matplotlib/issues/32](https://codeberg.org/Benjamin_Loison/matplotlib/issues/32).
Based on [the Stack Overflow question 23876588](https://stackoverflow.com/q/23876588):
Using:
```python
axis[0].set_title('First image without noise')
axis0 = axis[0].imshow(imageWithoutPrnuNpArrayTile)
plt.colorbar(axis0, label = 'Intensity', ax = axis[0])
```
With `tight_layout`:

Without `tight_layout`:

With `cax` instead of `ax`:

[The Stack Overflow answer 49037495](https://stackoverflow.com/a/49037495) code leads to:
```
/home/benjamin/.local/lib/python3.10/site-packages/matplotlib/projections/__init__.py:63: UserWarning: Unable to import Axes3D. This may be due to multiple versions of Matplotlib being installed (e.g. as a system package and as a pip package). As a result, the 3D projection is not available.
warnings.warn("Unable to import Axes3D. This may be due to multiple versions of "
Traceback (most recent call last):
File "<tmp 1>", line 14, in <module>
cax = divider.append_axes('right', size='5%', pad=0.05)
File "/home/benjamin/.local/lib/python3.10/site-packages/matplotlib/_api/deprecation.py", line 387, in wrapper
return func(*inner_args, **inner_kwargs)
File "/usr/lib/python3/dist-packages/mpl_toolkits/axes_grid1/axes_divider.py", line 552, in append_axes
ax = self.new_horizontal(size, pad, pack_start=False, **kwargs)
File "/usr/lib/python3/dist-packages/mpl_toolkits/axes_grid1/axes_divider.py", line 486, in new_horizontal
ax = self._get_new_axes(**kwargs)
File "/usr/lib/python3/dist-packages/mpl_toolkits/axes_grid1/axes_divider.py", line 437, in _get_new_axes
axes_class = axes._axes_class
AttributeError: 'Axes' object has no attribute '_axes_class'
```
[The Stack Overflow answer 23877042](https://stackoverflow.com/a/23877042) code leads to:
```
Traceback (most recent call last):
File "<tmp 2>", line 162, in <module>
plt.register_cmap(cmap=blue_red2)
AttributeError: module 'matplotlib.pyplot' has no attribute 'register_cmap'
```
The other answers to the mentioned Stack Overflow question do not seem interesting.
`orientation = 'horizontal'` makes the figure ok.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Related to #19, #27 and #9.
As Context-Adaptive Interpolator is slow and possibly incorrectly implemented, let us try a good known working denoiser:
Based on https://scikit-image.org/docs/0.22.x/auto_examples/filters/plot_denoise.html
With
PRNU_FACTOR = 0.1:PRNUquite guessable on a given image. Now need to reduce its factor and mean on several images to make it clear.With
PRNU_FACTOR = 0.01it is more subtile but still visible on both images. For the image with PRNU see theU. For the PRNU estimate look at the top ofRand bottom ofUfor instance.PRNU estimate taking into account all images:
Manipulating brightness and contrast on GIMP does not enable a clear result as the following one. However, the not significant RMS decreasing reason is unclear. Even with normalizing it does not seem to make sense.
Split images in 4x4 to increase PRNU estimation accuracy:
Let us not consider this RMS inconsistency but admit that the visual clear PRNU is fine, so let us add Gaussian noise.
In a first time we show an example of Gaussian noise and PRNU on an image, then we consider the PRNU estimate on the mean of the extracted noise for the considered images: in a first time only full images and in a second time split each images in 4x4.
With
NOISE_FACTOR = 0.25:With
NOISE_FACTOR = 0.1:If want to move on Gaussian noise as PRNU, then have to understand RMS unexpected results. May also be surprised, so can try anyway. To have recognizable PRNU can use
GIMP>Filters>Noise>RGB Noise...selecting white and setting{Red,Blue,Green}to1.Concerning the RMS, maybe it is due to residual scene and with more images we would have a many pixels, hence important, less significant as nearer to 0.
How to ease visualizing the values of this rendering of image of floats? Could render as a greyscale image to make sure of my rough understanding of image values.
I start having the feeling that the RMS inconsistency is because of the PRNU estimation background which can not converge to 0 as it is just adding residual scene.
The associated code is at
dd7a6892e5/datasets/noise_free_test_images/estimate_prnu.py.Next step:
Try on known working old cameras, i.e. with actual noise and PRNU? See #29.
Add a single or multiple color scales?
Related to Benjamin_Loison/matplotlib/issues/32.
Based on the Stack Overflow question 23876588:
Using:
With
tight_layout:Without
tight_layout:With
caxinstead ofax:The Stack Overflow answer 49037495 code leads to:
The Stack Overflow answer 23877042 code leads to:
The other answers to the mentioned Stack Overflow question do not seem interesting.
orientation = 'horizontal'makes the figure ok.Related to Benjamin_Loison/matplotlib/issues/35.
Should check the denoiser range. There is no denoiser here.
Could use the scikit util view as block/window.
Estimating fake PRNU on noise-less imagesto Estimating fake PRNU on noise-free imagesRelated to PRNU_extraction/issues/34.