mirror of
https://github.com/c-sooyoung/fold_slice.git
synced 2026-09-17 21:49:08 +09:00
initial commit
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
% find_shift_3D_nonrigid - GPU accelerated weighted optical flow method
|
||||
%
|
||||
% [shift,err] = find_shift_3D_nonrigid(vol_def, vol_ref, weight, downsample, smooth, regul)
|
||||
%
|
||||
% Inputs:
|
||||
% **vol_def deformed volume
|
||||
% **vol_ref reference volume
|
||||
% **weight importance weights for each pixel
|
||||
% **downsample downscale factor from the volume to DVF size
|
||||
% **smooth smoothness parameres for the recovered DVF
|
||||
% **regul regularization preventing empty regions to have too large effect on the DVF estimate
|
||||
% Outputs:
|
||||
% ++shift calculated local shift for reference to match deformed volume
|
||||
% ++err error between reference and the deformed volume
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| Except where otherwise noted, this work is licensed under a |
|
||||
%| Creative Commons Attribution-NonCommercial-ShareAlike 4.0 |
|
||||
%| International (CC BY-NC-SA 4.0) license. |
|
||||
%| |
|
||||
%| Copyright (c) 2018 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
%| |
|
||||
%| Author: CXS group, PSI |
|
||||
%*-----------------------------------------------------------------------*
|
||||
% You may use this code with the following provisions:
|
||||
%
|
||||
% If the code is fully or partially redistributed, or rewritten in another
|
||||
% computing language this notice should be included in the redistribution.
|
||||
%
|
||||
% If this code, or subfunctions or parts of it, is used for research in a
|
||||
% publication or if it is fully or partially rewritten for another
|
||||
% computing language the authors and institution should be acknowledged
|
||||
% in written form in the publication: “Data processing was carried out
|
||||
% using the “cSAXS matlab package” developed by the CXS group,
|
||||
% Paul Scherrer Institut, Switzerland.”
|
||||
% Variations on the latter text can be incorporated upon discussion with
|
||||
% the CXS group if needed to more specifically reflect the use of the package
|
||||
% for the published work.
|
||||
%
|
||||
% A publication that focuses on describing features, or parameters, that
|
||||
% are already existing in the code should be first discussed with the
|
||||
% authors.
|
||||
%
|
||||
% This code and subroutines are part of a continuous development, they
|
||||
% are provided “as they are” without guarantees or liability on part
|
||||
% of PSI or the authors. It is the user responsibility to ensure its
|
||||
% proper use and the correctness of the results.
|
||||
|
||||
|
||||
function [shift,err] = find_shift_3D_nonrigid(vol_def, vol_ref, weight, downsample, smooth, regul)
|
||||
|
||||
import plotting.*
|
||||
|
||||
|
||||
% calculate error
|
||||
resid = vol_def-vol_ref;
|
||||
|
||||
|
||||
% apply high pass filtering
|
||||
resid = resid - utils.imgaussfilt3_fft(resid, 5);
|
||||
|
||||
% calculate the error between the volumes
|
||||
err = weight .* resid.^2;
|
||||
err = sqrt(mean(err(:)));
|
||||
|
||||
% avoid numerical instabilities
|
||||
weight = weight / mean(abs(resid(:)));
|
||||
|
||||
Npix = size(vol_ref);
|
||||
for i = 1:3
|
||||
ind_def{i} = gpuArray(linspace(1,Npix(i)/downsample, Npix(i))');
|
||||
end
|
||||
[X,Y,Z]= meshgrid(ind_def{:});
|
||||
|
||||
|
||||
for ax = 1:3
|
||||
% get gradient direction
|
||||
vol_def_diff = math.get_img_grad_conv( vol_ref,2,ax);
|
||||
|
||||
% estimate the optimal step
|
||||
% GPU kernel merging
|
||||
[num, denum]= arrayfun(@get_coefs,weight, resid, vol_def_diff);
|
||||
|
||||
% bin the volume to make smoothing faster
|
||||
num = utils.binning_3D(num, downsample);
|
||||
denum = utils.binning_3D(denum, downsample);
|
||||
|
||||
num = padded_3D_smoothing(num, smooth/downsample/2);
|
||||
denum = padded_3D_smoothing(denum, smooth/downsample/2);
|
||||
|
||||
% add some small regularization
|
||||
denum = bsxfun(@plus, denum , regul*mean2(denum));
|
||||
|
||||
|
||||
shift{ax} = - num ./ denum;
|
||||
|
||||
% run simple line search to refined the optimal step, ideal it should be close to 1
|
||||
shift_full = interp3(shift{ax}, X,Y,Z);
|
||||
update = shift_full.*vol_def_diff;
|
||||
|
||||
Nsteps = 10;
|
||||
steps = logspace(0,1,Nsteps);
|
||||
for ii = 1:Nsteps
|
||||
res = arrayfun(@get_residuum_err, weight, resid,update, steps(ii));
|
||||
err_tmp(ii) = gather(sum(sum(sum(res))));
|
||||
if ii > 1 && err_tmp(ii) > err_tmp(ii-1)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
%% update the step
|
||||
shift{ax} = shift{ax} .* steps(math.argmin(err_tmp));
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
function [num, denum]= get_coefs(W, resid, grad)
|
||||
% auxiliary function for fast GPU calculations
|
||||
agrad = abs(grad);
|
||||
W = W .* agrad;
|
||||
% estimate the optimal step
|
||||
num = W .* real(conj(resid) .* grad);
|
||||
denum = W .* agrad.^2;
|
||||
|
||||
|
||||
end
|
||||
|
||||
function res = get_residuum_err(weight, resid, update, step)
|
||||
res = weight .* (resid + step.* update).^2;
|
||||
end
|
||||
|
||||
function array = padded_3D_smoothing(array, smooth, split)
|
||||
% prevent periodic boundary issues for FFT conv smoothing
|
||||
if nargin < 3
|
||||
split = 1;
|
||||
end
|
||||
|
||||
Npad = ceil(min(size(array)/2, ceil(smooth/8)*16));
|
||||
array = padarray(array,[Npad(1),0,0],'symmetric','both');
|
||||
array = padarray(array,[0,Npad(2),0],'symmetric','both');
|
||||
array = padarray(array,[0,0,Npad(3)],'symmetric','both');
|
||||
|
||||
array = utils.imgaussfilt3_fft(array, smooth, split);
|
||||
|
||||
array = array(Npad(1):end-Npad(1)-1, Npad(2):end-Npad(2)-1,Npad(3):end-Npad(3)-1);
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user