Author: Roland Kwitt, Kitware Inc., 2013 (roland.kwitt@kitware.com, rkwitt@gmx.at)
Our problem setting is as follows: We want to load an image (which we know is low-rank due to it's structure), then corrupt the image with random outliers and eventually recover the low-rank part (i.e., the original image).
Let's load SimpleITK and numpy first:
In [78]:
import SimpleITK as sitk
import numpy as np
We'll tackle the task using ialm, i.e., the Inexact Lagrangian Multipier (IALM) approach:
In [79]:
import core.ialm as ialm
We next load a checkerboard image (our low-rank signal):
In [80]:
I = sitk.ReadImage("examples/checkerboard.png")
In [81]:
Inp = sitk.GetArrayFromImage(I)
In [82]:
imshow(Inp, cm.gray)
Out[82]:
As we can see, the image has a very distinctive structure. In the following, we'll corrupt 30% of the pixel values by pertubing the signal with values in the range [190, 210]. The outliers will be uniformly distributed.
In [83]:
p = 0.3
how_many = np.round(N*p)
outliers = np.round(np.random.uniform(-10, 10, how_many))
In [84]:
N = np.prod(Inp.shape)
where = np.random.random_integers(0, N-1, how_many)
We create a copy of the original image and set the outliers:
In [85]:
Inp_corrupted = np.copy(Inp)
In [97]:
Inp_corrupted.ravel()[where] = np.array(200 + outliers, dtype=np.uint8)
In [98]:
imshow(Inp_corrupted, cm.gray)
Out[98]:
We'll run IALM (with it's default settings) on the image next which gives us the low-rank and the sparse (hopefully the outliers) signal parts:
In [99]:
low_rank, sparse, _ = ialm.recover(Inp_corrupted)
In [100]:
imshow(low_rank, cm.gray)
Out[100]:
In [93]:
imshow(sparse, cm.gray)
Out[93]:
In [102]:
# compute Frobenius norm of low-rank part minus the original signal
error = np.linalg.norm(low_rank-Inp,ord='fro')
print error
In [114]:
# compute Frobenius norm
error = np.linalg.norm(np.abs(np.round(low_rank))-Inp,'fro')
print error
So, in the end, we could perfectly separate the low-rank and sparse part of this signal.