Search code examples
pythonpcanoise-reduction

How to apply PCA to an image


I have a graycale noisy image. I want to apply PCA for noise reduction and see the output after the application.

Here's what I tried to do:

[in]:


from sklearn.datasets import load_sample_image
from sklearn.feature_extraction import image
from sklearn.decomposition import PCA
# Create patches of size 25 by 25 and create a matrix from all patches
patches = image.extract_patches_2d(grayscale_image, (25, 25), random_state = 42)
print(patches.shape)
# reshape patches because I got an error when applying fit_transform(ValueError: FoundValueError: Found array with dim 3. Estimator expected <= 2.)
patches_reshaped = patches.reshape(2,-1)
#apply PCA
pca = PCA()
projected = pca.fit_transform(patches_reshaped.data)
denoised_image = pca.inverse_transform(projected)
imshow(denoised_image)

[out]:

pca_result
(source: imggmi.com)

I get an array as a result. How to see the de-noised image?


Solution

  • In order to see your de-noised image, you need to convert your data which is represented in some low-dimension using the principal components back to the original space. To do that you can use the inverse_transform() function. As you can see from the documentation here, this function will accept the projected data and return an array like the original image. So you can do something like,

    denoised_image = pca.inverse_transform(projected)
    # then view denoised_image
    

    Edit:

    Here are some of the issues to look in to:

    1. You have 53824 patches from your original image with sizes (25,25). In order to reshape you data and pass it to PCA, as you can see from the documentation here, you need to pass an array of size (n_samples, n_features). Your number of samples is 53824. So patches reshaped should be:
    patches_reshaped = patches.reshape(patches.shape[0],-1)
    # this should return a (53824, 625) shaped data
    
    1. Now you use this reshaped data and transform it using PCA and inverse transform to get the data in your original domain. After doing that, your denoised_image is a set of reconstructed patches. You will need to combine these patches to get an image using the function image.reconstruct_from_patches_2d here is the documentation. So you can do something like,
    denoised_image = image.reconstruct_from_patches_2d(denoised_image.reshape(-1,25,25), grayscale_image.shape)
    

    Now you can view the denoised_image, which should look like grayscale_image.