2

In the following code I am using Python's pillow/PIL library. I have successfully been able to read in an image file and store it as a matrix, access the red, blue, green channel which is an unsigned integer unit8 and convert each channel to float64.

However now I am looking to see if I did the next part correct. In my code below in addition to the above details I have applied the svd from numpy.linalg to each channel. Have I done this correctly? Also how might I use it to compute the rank-k approximation? Any help is greatly appreciated as I am not sure how I would compute the rank-k approximation if I implemented the svd from numpy.linalg to each channel correctly

Here is my code:

import numpy as np
from PIL import Image
img = Image.open('house.jpg')
image = np.array(img)
arr[20,30]
red = np.float64(image[:,:, 0])
green = np.float64(image[:,:,1])
blue = np.float64(image[:,:,2])

Applying it to the red channel:

P, D, Q = np.linalg.svd(red, full_matrices=False)
red_a = np.matmul(np.matmul(P, np.diag(D)), Q)
print(np.std(red), np.std(red_a), np.std(red - red_a))

resulting in:

58.34304856581507 58.34304856581494 9.996264017664882e-13

Applying it to the green channel:

P, D, Q = np.linalg.svd(green, full_matrices=False)
green_a = np.matmul(np.matmul(P, np.diag(D)), Q)
print(np.std(green), np.std(green_a), np.std(green - green_a))

resulting in:

51.90828777139797 51.90828777139794 2.5106850520519223e-13

finally applying it to the blue channel:

P, D, Q = np.linalg.svd(blue, full_matrices=False)
blue_a = np.matmul(np.matmul(P, np.diag(D)), Q)
print(np.std(blue), np.std(blue_a), np.std(blue - blue_a))

resulting in:

77.28319292372947 77.28319292372947 1.4848230006060346e-12
fr14
  • 717
  • 3
  • 10
  • 23
  • https://math.stackexchange.com/questions/2911286/how-to-apply-svd-to-real-data-to-reduce-the-number-of-parameters/2911333#2911333 this is an answer I wrote implementing the truncated SVD in python. –  Oct 28 '18 at 21:27

1 Answers1

1

I'm not certain if what you're doing works because of you're taking image data. I think a different approach needs to be done.

import numpy as np
from PIL import Image
img = Image.open('house.jpg')
image = np.array(img)

red = np.float64(image[:,:, 0])
green = np.float64(image[:,:,1])
blue = np.float64(image[:,:,2])

def low_rank_k(u,s,vh,num):
# rank k approx

    u = u[:,:num]
    vh = vh[:num,:]
    s = s[:num]
    s = np.diag(s)
    my_low_rank = np.dot(np.dot(u,s),vh)
    return my_low_rank

# Take the svd
u,s,vh = np.linalg.svd(red, full_matrices= False)
# determine the matrix rank
my_rank_r = np.linalg.matrix_rank(red)
# generate the rank k approximation
my_rank_k_r = low_rank_k(u,s,vh,my_rank_r)

u,s,vh = np.linalg.svd(green,full_matrices=False)
my_rank_g = np.linalg.matrix_rank(green)
my_rank_k_g = low_rank_k(u,s,vh,my_rank_g)

u,s,vh = np.linalg.svd(blue,full_matrices=False)
my_rank_b = np.linalg.matrix_rank(blue)
my_rank_k_b = low_rank_k(u,s,vh,my_rank_b)


new_red = np.uint8(my_rank_k_r)
new_green = np.uint8(my_rank_k_g)
new_blue = np.uint8(my_rank_k_b)

my_array = np.array([new_red,new_green,new_blue])

note this array isn't right..