Permalink
Browse files

added nuclear norm and corresponding prox operator

  • Loading branch information...
LarsHaalck committed Apr 2, 2018
1 parent 1bc972e commit e62125650e9e4a39cf09c08099ee75d1197ac26e
Showing with 96 additions and 0 deletions.
  1. +58 −0 examples/exampleNuclearNorm.m
  2. +27 −0 prox/nuclearProxDual.m
  3. +11 −0 terms/regularizer/nuclearIdentity.m
@@ -0,0 +1,58 @@
clear all;close all;clc;
%% read data
addpath(genpath('..'));
image = im2double((imread('data/test.png')));
if (size(image,3) > 1)
image = rgb2gray(image);
end
imageNoisy = imnoise(image, 'salt & pepper', 0.01);
%show clean input and noisy image
figure(1);imagesc(image);axis image;colormap(gray);title('Input Image')
figure(2);imagesc(imageNoisy);axis image;colormap(gray);title('Noisy Image')
%% FlexBox
main = flexBox;
main.params.tryCPP = 0;
numberL = main.addPrimalVar(size(image));
numberS = main.addPrimalVar(size(image));
weightL2 = 3;
weightNuclear = 0.3;
weightL1 = 0.01;
%Dx = gradientOperator(size(dataPart), 1);
%Dy = gradientOperator(size(dataPart), 2);
%func = @(x) weightL2/2 * norm(x - dataPart, 2)^2 + weightL2Inf * sqrt(max(Dx*x(:).^2 + Dy*x(:).^2));
nPx = numel(image);
%data term: 1/2 * || id*(L+S) - f||
main.addTerm(L2dataTermOperator(weightL2,{identityOperator(nPx), identityOperator(nPx)},imageNoisy),[numberL, numberS]);
%main.addTerm(L2dataTerm(weightL2,imageNoisy),numberL);
%nuclear norm regularizer
main.addTerm(nuclearIdentity(weightNuclear,size(image)), numberL);
%1-norm regularizer (doesnt matter if L1
main.addTerm(L1identity(weightL1,size(image)), numberS);
%run minimization algorithm
tic;main.runAlgorithm;toc;
%% get result
minLFlex = main.getPrimal(numberL);
minSFlex = main.getPrimal(numberS);
figure(3);imshow(minLFlex);title('L')
%[U,S,V] = svd(minLFlex);
%sum(diag(S))
%% print results
figure(4);imagesc(minSFlex);axis image;colormap(gray);title('S');
figure(5);imagesc(minLFlex + minSFlex);axis image;colormap(gray);title('L+S');
figure(6);imagesc(minLFlex + minSFlex - imageNoisy);axis image;colormap(gray);title('L+S - data');
figure(7);imagesc(minLFlex - image);axis image;colormap(gray);title('L - original');
@@ -0,0 +1,27 @@
classdef nuclearProxDual < basicProx
properties
end
methods
function obj = nuclearProxDual()
end
function applyProx(obj,main,dualNumbers,~)
for i=1:obj.numVars
%reshape dual variable back to matrix form
mat = reshape(main.yTilde{dualNumbers(i)}, main.dims{main.DcP{dualNumbers(i)}});
%retrieve singular values
[U,S,V] = svd(mat);
svs = diag(S);
%evaluate L1 prox for singular values
proxSvs = max(-obj.factor, min(obj.factor, svs));
%reconstruct
mat = U*diag(proxSvs)*V';
main.y{dualNumbers(i)} = mat(:);
end
end
end
end
@@ -0,0 +1,11 @@
classdef nuclearIdentity < basicIdentity & nuclearProxDual
properties
end
methods
function obj = nuclearIdentity(alpha,dims)
obj = obj@basicIdentity(alpha,dims);
end
end
end

0 comments on commit e621256

Please sign in to comment.