├── LICENSE ├── README.md └── Tensor_RPCA.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Toshiki S Yamano 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tensor_RPCA 2 | Tensor Robust Principal Component Analysis via t-SVD 3 | _Tensor Robust Principal Component Analysis_ 4 | 5 | This is a code for TRPCA by t-SVD. 6 | You can see the original paper (CVPR 2016) from 7 | 8 | This code is to denoise image by using TRPCA. 9 | For optimization algorithm, I used ADMM. 10 | -------------------------------------------------------------------------------- /Tensor_RPCA.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from matplotlib import pylab as plt 3 | from numpy.linalg import svd 4 | from PIL import Image 5 | 6 | class TRPCA: 7 | 8 | def converged(self, L, E, X, L_new, E_new): 9 | ''' 10 | judge convered or not 11 | ''' 12 | eps = 1e-8 13 | condition1 = np.max(L_new - L) < eps 14 | condition2 = np.max(E_new - E) < eps 15 | condition3 = np.max(L_new + E_new - X) < eps 16 | return condition1 and condition2 and condition3 17 | 18 | def SoftShrink(self, X, tau): 19 | ''' 20 | apply soft thesholding 21 | ''' 22 | z = np.sign(X) * (abs(X) - tau) * ((abs(X) - tau) > 0) 23 | 24 | return z 25 | 26 | def SVDShrink(self, X, tau): 27 | ''' 28 | apply tensor-SVD and soft thresholding 29 | ''' 30 | W_bar = np.empty((X.shape[0], X.shape[1], 0), complex) 31 | D = np.fft.fft(X) 32 | for i in range (3): 33 | if i < 3: 34 | U, S, V = svd(D[:, :, i], full_matrices = False) 35 | S = self.SoftShrink(S, tau) 36 | S = np.diag(S) 37 | w = np.dot(np.dot(U, S), V) 38 | W_bar = np.append(W_bar, w.reshape(X.shape[0], X.shape[1], 1), axis = 2) 39 | if i == 3: 40 | W_bar = np.append(W_bar, (w.conjugate()).reshape(X.shape[0], X.shape[1], 1)) 41 | return np.fft.ifft(W_bar).real 42 | 43 | 44 | def ADMM(self, X): 45 | ''' 46 | Solve 47 | min (nuclear_norm(L)+lambda*l1norm(E)), subject to X = L+E 48 | L,E 49 | by ADMM 50 | ''' 51 | m, n, l = X.shape 52 | rho = 1.1 53 | mu = 1e-3 54 | mu_max = 1e10 55 | max_iters = 1000 56 | lamb = (max(m, n) * l) ** -0.5 57 | L = np.zeros((m, n, l), float) 58 | E = np.zeros((m, n, l), float) 59 | Y = np.zeros((m, n, l), float) 60 | iters = 0 61 | while True: 62 | iters += 1 63 | # update L(recovered image) 64 | L_new = self.SVDShrink(X - E + (1/mu) * Y, 1/mu) 65 | # update E(noise) 66 | E_new = self.SoftShrink(X - L_new + (1/mu) * Y, lamb/mu) 67 | Y += mu * (X - L_new - E_new) 68 | mu = min(rho * mu, mu_max) 69 | if self.converged(L, E, X, L_new, E_new) or iters >= max_iters: 70 | return L_new, E_new 71 | else: 72 | L, E = L_new, E_new 73 | print(np.max(X - L - E)) 74 | 75 | 76 | # Load Data 77 | X = np.array(Image.open(r'photo.jpg')) 78 | 79 | # add noise(make some pixels black at the rate of 10%) 80 | k = np.random.rand(X.shape[0], X.shape[1]) > 0.1 81 | K = np.empty((X.shape[0], X.shape[1], 0), np.uint8) 82 | for i in range (3): 83 | K = np.append(K, k.reshape(X.shape[0], X.shape[1], 1), axis = 2) 84 | X_bar = X * K 85 | 86 | # image denoising 87 | TRPCA = TRPCA() 88 | L, E = TRPCA.ADMM(X) 89 | L = np.array(L).astype(np.uint8) 90 | E = np.array(E).astype(np.uint8) 91 | plt.subplot(131) 92 | plt.imshow(X) 93 | plt.title('original image') 94 | plt.subplot(132) 95 | plt.imshow(X_bar) 96 | plt.title('image with noise') 97 | plt.subplot(133) 98 | plt.imshow(L) 99 | plt.title('recovered image') 100 | plt.show() 101 | --------------------------------------------------------------------------------