Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Initial release
  • Loading branch information
uschmidt83 committed May 7, 2014
0 parents commit 6a612e4
Show file tree
Hide file tree
Showing 93 changed files with 1,919 additions and 0 deletions.
16 changes: 16 additions & 0 deletions +misc/separate_blocks.m
@@ -0,0 +1,16 @@
%SEPARATE_BLOCKS - Enlarge 2D image by inserting a margin between blocks of a given size.

% Author: Uwe Schmidt, TU Darmstadt (uwe.schmidt@gris.tu-darmstadt.de)
%
% This file is part of the implementation as described in the CVPR 2014 paper:
% Uwe Schmidt and Stefan Roth. Shrinkage Fields for Effective Image Restoration.
% Please see the file LICENSE.txt for the license governing this code.

function I = separate_blocks(I,blockdims,pad,pad_val)
if ~exist('pad','var'), pad = 1; end
if ~exist('pad_val','var'), pad_val = nan; end

blockfunc = @(b) padarray(b.data,[pad,pad],pad_val,'pre');
I = blockproc(I,blockdims,blockfunc);
I = padarray(I,[pad,pad],pad_val,'post');
end
19 changes: 19 additions & 0 deletions +misc/struct2vec.m
@@ -0,0 +1,19 @@
%STRUCT2VEC - Convert a STRUCT to a row vector.
% See also VEC2STRUCT.

% Author: Uwe Schmidt, TU Darmstadt (uwe.schmidt@gris.tu-darmstadt.de)
%
% This file is part of the implementation as described in the CVPR 2014 paper:
% Uwe Schmidt and Stefan Roth. Shrinkage Fields for Effective Image Restoration.
% Please see the file LICENSE.txt for the license governing this code.

function vec = struct2vec(theta)
assert(isstruct(theta));
% theta = orderfields(theta);
fnames = fieldnames(theta);
vec = [];
for i = 1:numel(fnames)
value = theta.(fnames{i});
vec = [vec; value(:)]; %#ok
end
end
13 changes: 13 additions & 0 deletions +misc/struct_put.m
@@ -0,0 +1,13 @@
%STRUCT_PUT - Set fields of a STRUCT based on the names and contents of provided arguments.

% Author: Uwe Schmidt, TU Darmstadt (uwe.schmidt@gris.tu-darmstadt.de)
%
% This file is part of the implementation as described in the CVPR 2014 paper:
% Uwe Schmidt and Stefan Roth. Shrinkage Fields for Effective Image Restoration.
% Please see the file LICENSE.txt for the license governing this code.

function s = struct_put(s, varargin)
for i = 1:numel(varargin)
s.(inputname(i+1)) = varargin{i};
end
end
28 changes: 28 additions & 0 deletions +misc/vec2struct.m
@@ -0,0 +1,28 @@
%VEC2STRUCT - Convert a row vector to a STRUCT (based on the provided template).
% See also STRUCT2VEC.

% Author: Uwe Schmidt, TU Darmstadt (uwe.schmidt@gris.tu-darmstadt.de)
%
% This file is part of the implementation as described in the CVPR 2014 paper:
% Uwe Schmidt and Stefan Roth. Shrinkage Fields for Effective Image Restoration.
% Please see the file LICENSE.txt for the license governing this code.

function theta = vec2struct(vec, THETA)
assert(isstruct(THETA));
% theta = orderfields(THETA);
theta = THETA;
fnames = fieldnames(theta);
e = 0; % end-point
for i = 1:numel(fnames)
field_size = size(theta.(fnames{i}));
field_numel = prod(field_size);
% special case of last field that takes remaining elements of vec
if field_numel == 0 && i == numel(fnames)
field_numel = numel(vec)-e;
field_size = [field_numel,1];
end
field_value = reshape( vec(e+1:e+field_numel), field_size );
theta.(fnames{i}) = field_value;
e = e + field_numel;
end
end
29 changes: 29 additions & 0 deletions +misc/vis_bndry.m
@@ -0,0 +1,29 @@
%VIS_BNDRY - Visualize image boundary (and embed blur kernel).

% Author: Uwe Schmidt, TU Darmstadt (uwe.schmidt@gris.tu-darmstadt.de)
%
% This file is part of the implementation as described in the CVPR 2014 paper:
% Uwe Schmidt and Stefan Roth. Shrinkage Fields for Effective Image Restoration.
% Please see the file LICENSE.txt for the license governing this code.

function x = vis_bndry(x,k,t)
if t > 0
% scale by inner region
x_inside = x(1+t:end-t,1+t:end-t);
x = x - min(x_inside(:));
x = x / max(x_inside(:));
% clip values at boundary
x = min(max(x,0),1);

x = repmat(x,[1,1,3]);
x([1+t,end-t],1+t:end-t,:) = 0;
x([1+t,end-t],1+t:end-t,2) = 1;
x(1+t:end-t,[1+t,end-t],:) = 0;
x(1+t:end-t,[1+t,end-t],2) = 1;
if numel(k) > 1
kdims = size(k);
k = k / max(k(:));
x(1:kdims(1),1:kdims(2),:) = repmat(k,[1,1,3]);
end
end
end
20 changes: 20 additions & 0 deletions +train/edgetaper_alpha.m
@@ -0,0 +1,20 @@
%EDGETAPER_ALPHA - Weights for edge tapering.
% Based on Matlab's EDGETAPER function,
% and used as in Sec. 1.1. of the supplemental material.
%
% See also EDGETAPER.

% Author: Uwe Schmidt, TU Darmstadt (uwe.schmidt@gris.tu-darmstadt.de)
%
% This file is part of the implementation as described in the CVPR 2014 paper:
% Uwe Schmidt and Stefan Roth. Shrinkage Fields for Effective Image Restoration.
% Please see the file LICENSE.txt for the license governing this code.

function alpha = edgetaper_alpha(k,imdims)
assert(all(imdims > 2*size(k)), 'kernel too small for image size')
alpha = 1;
for i = 1:2
z = real(ifft(abs(fft(sum(k,3-i),imdims(i)-1)).^2));
alpha = alpha * (1 - z([1:end,1])/max(z));
end
end
12 changes: 12 additions & 0 deletions +train/filter_circ_conv.m
@@ -0,0 +1,12 @@
%FILTER_CIRC_CONV - 2D convolution with circular boundary handling.

% Author: Uwe Schmidt, TU Darmstadt (uwe.schmidt@gris.tu-darmstadt.de)
%
% This file is part of the implementation as described in the CVPR 2014 paper:
% Uwe Schmidt and Stefan Roth. Shrinkage Fields for Effective Image Restoration.
% Please see the file LICENSE.txt for the license governing this code.

function r = filter_circ_conv(img,j,s)
r = imfilter(img,s.f{j},'same','circular','conv');
% r = real( ifft2( s.f_otf{j} .* fft2(img)) );
end
12 changes: 12 additions & 0 deletions +train/filter_circ_corr.m
@@ -0,0 +1,12 @@
%FILTER_CIRC_CORR - 2D correlation with circular boundary handling.

% Author: Uwe Schmidt, TU Darmstadt (uwe.schmidt@gris.tu-darmstadt.de)
%
% This file is part of the implementation as described in the CVPR 2014 paper:
% Uwe Schmidt and Stefan Roth. Shrinkage Fields for Effective Image Restoration.
% Please see the file LICENSE.txt for the license governing this code.

function r = filter_circ_corr(img,j,s)
r = imfilter(img,s.f{j},'same','circular','corr');
% r = real( ifft2( s.f_otf_tr{j} .* fft2(img)) );
end
30 changes: 30 additions & 0 deletions +train/fix_bndry.m
@@ -0,0 +1,30 @@
%FIX_BNDRY - Boundary operations (padding, truncation, edge tapering).
% See Sec. 1.1. of the supplemental material.

% Author: Uwe Schmidt, TU Darmstadt (uwe.schmidt@gris.tu-darmstadt.de)
%
% This file is part of the implementation as described in the CVPR 2014 paper:
% Uwe Schmidt and Stefan Roth. Shrinkage Fields for Effective Image Restoration.
% Please see the file LICENSE.txt for the license governing this code.

function I = fix_bndry(I,k,alpha,s,transpose)
if ~exist('transpose','var'), transpose = false; end
if transpose
if numel(k)~=1 || k ~= 1 % no edgetapering when denoising
I = s.rs(I);
for i = 1:s.ntapers
blurredI = train.kernel_circ((1-alpha).*I,k,'corr',s);
I = alpha.*I + blurredI;
end
end
I = s.rs(s.PT' * I(:));
else
I = s.rs(s.PT * I(:));
if numel(k)~=1 || k ~= 1 % no edgetapering when denoising
for i = 1:s.ntapers
blurredI = train.kernel_circ(I,k,'conv',s);
I = alpha.*I + (1-alpha).*blurredI;
end
end
end
end
55 changes: 55 additions & 0 deletions +train/get_data.m
@@ -0,0 +1,55 @@
%GET_DATA - Load and generate training data.

% Author: Uwe Schmidt, TU Darmstadt (uwe.schmidt@gris.tu-darmstadt.de)
%
% This file is part of the implementation as described in the CVPR 2014 paper:
% Uwe Schmidt and Stefan Roth. Shrinkage Fields for Effective Image Restoration.
% Please see the file LICENSE.txt for the license governing this code.

function data = get_data(p,s)

assert(s.nimages <= 20);
assert(all([128,128]==s.imdims) && s.npixels == prod(s.imdims), 'size must be 128x128 pixels in this example')

[X,Y] = deal(zeros(s.npixels,s.nimages));
if s.is_deblurring
ks = cell(s.nimages,1);
alphas = zeros([s.imdims,s.nimages]);
else
[ks,alphas] = deal([]);
end

for i = 1:s.nimages
fprintf('Loading image %02d/%02d\r',i,s.nimages);
img = double(imread(sprintf('%s/images/image_%02d.png',p,i)));
X(:,i) = img(:);

if s.is_deblurring
k = dlmread(sprintf('%s/kernels/image_%02d.dlm',p,i),'\t'); k = k/sum(k(:));
blurred = conv2(img,k,'valid');
blurred = blurred + s.sigma * randn(size(blurred));
blurred = double(uint8(blurred));

% suboptimal, but simplifies training: pad all kernels with 0s to have the same size (s.k_sz_max)
kdims = size(k); assert(all(mod(s.k_sz_max-kdims,2)==0))
k = padarray(k,(s.k_sz_max-kdims)/2,0,'both'); ks{i} = k;
% crop blurred image to correct for kernel padding
excess = (size(k)-kdims)/2;
blurred = blurred(1+excess(1):end-excess(1),1+excess(2):end-excess(2));
% padarray & edgetaper
alphas(:,:,i) = train.edgetaper_alpha(k,s.imdims);
blurred = train.fix_bndry(s.T'*blurred(:),ks{i},alphas(:,:,i),s);
Y(:,i) = blurred(:);
else
img = img + s.sigma * randn(size(img));
img = double(uint8(img));
Y(:,i) = s.PT * img(:); % truncate and pad corrupted images
end
end
fprintf('\n')

data = struct;
for str = {'nimages','imdims','npixels','sigma'}, data.(char(str)) = s.(char(str)); end
[data.X,data.Y,data.ks,data.alphas] = deal(X,Y,ks,alphas);

end
31 changes: 31 additions & 0 deletions +train/get_filters.m
@@ -0,0 +1,31 @@
%GET_FILTERS - Get filter bank.

% Author: Uwe Schmidt, TU Darmstadt (uwe.schmidt@gris.tu-darmstadt.de)
%
% This file is part of the implementation as described in the CVPR 2014 paper:
% Uwe Schmidt and Stefan Roth. Shrinkage Fields for Effective Image Restoration.
% Please see the file LICENSE.txt for the license governing this code.

function s = get_filters(s)

switch s.fbank
case 'pw'
s.f = {[1 -1 0];[1 -1 0]'};
case 'dct'
n = s.fbank_sz;
% dct filters without DC component
assert(mod(n,2)==1, 'filters must be odd-sized')
N = n^2;
s.f = cell(N-1,1);
s.filter_basis = zeros(N,N-1);
for i = 2:N
d = zeros(n,n); d(i) = 1;
s.f{i-1} = idct2(d');
s.filter_basis(:,i-1) = s.f{i-1}(:);
end
otherwise
error('unsupported fbank: %s', s.fbank)
end
s.nfilters = numel(s.f);

end
29 changes: 29 additions & 0 deletions +train/get_minimizer.m
@@ -0,0 +1,29 @@
%GET_MINIMIZER - Find suitable optimization algorithm.

% Author: Uwe Schmidt, TU Darmstadt (uwe.schmidt@gris.tu-darmstadt.de)
%
% This file is part of the implementation as described in the CVPR 2014 paper:
% Uwe Schmidt and Stefan Roth. Shrinkage Fields for Effective Image Restoration.
% Please see the file LICENSE.txt for the license governing this code.

function minimizer = get_minimizer(s, cost_func, theta0)

if exist('minFunc') == 2 %#ok
% 'minFunc' by Mark Schmidt (http://www.di.ens.fr/~mschmidt/Software/minFunc.html)
options = struct('MaxIter',s.maxoptiters);
if s.do_joint_training, minimizer = @() minFunc(cost_func,theta0,options);
else minimizer = @(U) minFunc(cost_func,theta0,options,U); end
elseif exist('minimize') == 2 %#ok
% 'minimize' by Carl Edward Rasmussen (http://www.gatsby.ucl.ac.uk/~edward/code/minimize/)
if s.do_joint_training, minimizer = @() minimize(theta0,cost_func,s.maxoptiters);
else minimizer = @(U) minimize(theta0,cost_func,s.maxoptiters,U); end
elseif exist('fminunc') == 2 %#ok
% 'fminunc' from Matlab's optimization toolbox (http://www.mathworks.de/help/optim/ug/fminunc.html)
options = optimset('MaxIter',s.maxoptiters, 'Display','iter', 'GradObj','on', 'LargeScale','off');
if s.do_joint_training, minimizer = @() fminunc(cost_func,theta0,options);
else minimizer = @(U) fminunc(cost_func,theta0,options,U); end
else
error('No suitable minimization algorithm found.')
end

end
65 changes: 65 additions & 0 deletions +train/grad_params.m
@@ -0,0 +1,65 @@
%GRAD_PARAMS - Compute gradient w.r.t. all model parameters of one stage of a shrinkage field cascade.
% See Sec. 1.2.2 of the supplemental material.
% See also OBJECTIVE_ONE_STAGE, OBJECTIVE_ALL_STAGES.

% Author: Uwe Schmidt, TU Darmstadt (uwe.schmidt@gris.tu-darmstadt.de)
%
% This file is part of the implementation as described in the CVPR 2014 paper:
% Uwe Schmidt and Stefan Roth. Shrinkage Fields for Effective Image Restoration.
% Please see the file LICENSE.txt for the license governing this code.

function [g,c_prev] = grad_params(s,x,x_old,y,k,alpha,c,lambda,gw,gx,z,fx_old,fnorms,bottom)
% c_prev is for the previous model stage as defined in Eq. (34) of the supplemental material

GRAD = struct;
do_c_prev = nargout == 2;
g_weights = zeros(size(gw{1},1),s.nfilters);
if s.do_filterlearning, g_filt = zeros(size(s.filter_basis,2),s.nfilters); end
if do_c_prev, c_prev = zeros(s.imdims); end

if s.do_filterlearning
cliques_c = s.filter_basis' * c(s.cliques_of_circ_conv);
cliques_x = s.filter_basis' * x(s.cliques_of_circ_conv);
cliques_x_old = s.filter_basis' * x_old(s.cliques_of_circ_conv);
end

% grad wrt. (log) lambda
if s.is_deblurring
kc = train.kernel_circ(c,k,'conv',s);
kx = train.kernel_circ(x,k,'conv',s);
GRAD.lambda = kc(:)' * (y(:)-kx(:));
else
GRAD.lambda = c(:)' * (y(:)- x(:));
end
GRAD.lambda = GRAD.lambda * lambda;

for j = 1:s.nfilters
fc = s.vec(train.filter_circ_conv(c,j,s));
% grad wrt. shrinkage weights
g_weights(:,j) = gw{j} * fc;
fc_gx = fc .* gx{j}(:);
if s.do_filterlearning
% grad wrt. filter coefficients
fx = s.vec(train.filter_circ_conv(x,j,s));
z_minus_fx = z{j}(:) - fx;
g_filt(:,j) = cliques_x_old*fc_gx + cliques_c*z_minus_fx - cliques_x*fc;
if s.unitnorm_filter
g_filt(:,j) = g_filt(:,j) - s.filter_basis' * s.f{j}(:) * (fc' * (fx_old{j}(:).*gx{j}(:) + z_minus_fx - fx));
g_filt(:,j) = g_filt(:,j) / fnorms(j);
end
end
% c for previous stage
if do_c_prev
c_prev = c_prev + train.filter_circ_corr(s.rs(fc_gx),j,s);
end
end
% c for previous stage
if do_c_prev
c_prev = real(ifft2( fft2(train.fix_bndry(c_prev,k,alpha,s,true)) ./ bottom ));
end

GRAD.weights = g_weights(:);
if s.do_filterlearning, GRAD.filters = g_filt(:); end
g = misc.struct2vec(GRAD);

end

0 comments on commit 6a612e4

Please sign in to comment.