mirror of
https://github.com/c-sooyoung/fold_slice.git
synced 2026-09-17 23:39:08 +09:00
100 lines
3.6 KiB
Matlab
100 lines
3.6 KiB
Matlab
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% Unwrapping phase based on Ghiglia and Romero (1994) based on weighted and unweighted least-square method
|
|
% URL: https://doi.org/10.1364/JOSAA.11.000107
|
|
% Inputs:
|
|
% * psi: wrapped phase from -pi to pi
|
|
% * weight: weight of the phase (optional, default: all ones)
|
|
% Output:
|
|
% * phi: unwrapped phase from the weighted (or unweighted) least-square phase unwrapping
|
|
% Author: Muhammad F. Kasim (University of Oxford, 2016)
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
function phi = phase_unwrap(psi, weight)
|
|
if (nargin < 2) % unweighted phase unwrap
|
|
% get the wrapped differences of the wrapped values
|
|
dx = [zeros([size(psi,1),1]), wrapToPi(diff(psi, 1, 2)), zeros([size(psi,1),1])];
|
|
dy = [zeros([1,size(psi,2)]); wrapToPi(diff(psi, 1, 1)); zeros([1,size(psi,2)])];
|
|
rho = diff(dx, 1, 2) + diff(dy, 1, 1);
|
|
|
|
% get the result by solving the poisson equation
|
|
phi = solvePoisson(rho);
|
|
|
|
else % weighted phase unwrap
|
|
% check if the weight has the same size as psi
|
|
if (~all(size(weight) == size(psi)))
|
|
error('Argument error: Size of the weight must be the same as size of the wrapped phase');
|
|
end
|
|
|
|
% vector b in the paper (eq 15) is dx and dy
|
|
dx = [wrapToPi(diff(psi, 1, 2)), zeros([size(psi,1),1])];
|
|
dy = [wrapToPi(diff(psi, 1, 1)); zeros([1,size(psi,2)])];
|
|
|
|
% multiply the vector b by weight square (W^T * W)
|
|
WW = weight .* weight;
|
|
WWdx = WW .* dx;
|
|
WWdy = WW .* dy;
|
|
|
|
% applying A^T to WWdx and WWdy is like obtaining rho in the unweighted case
|
|
WWdx2 = [zeros([size(psi,1),1]), WWdx];
|
|
WWdy2 = [zeros([1,size(psi,2)]); WWdy];
|
|
rk = diff(WWdx2, 1, 2) + diff(WWdy2, 1, 1);
|
|
normR0 = norm(rk(:));
|
|
|
|
% start the iteration
|
|
eps = 1e-6;
|
|
k = 0;
|
|
phi = zeros(size(psi));
|
|
while (~all(rk == 0))
|
|
zk = solvePoisson(rk);
|
|
k = k + 1;
|
|
if (k == 1) pk = zk;
|
|
else
|
|
betak = sum(sum(rk .* zk)) / sum(sum(rkprev .* zkprev));
|
|
pk = zk + betak * pk;
|
|
end
|
|
|
|
% save the current value as the previous values
|
|
rkprev = rk;
|
|
zkprev = zk;
|
|
|
|
% perform one scalar and two vectors update
|
|
Qpk = applyQ(pk, WW);
|
|
alphak = sum(sum(rk .* zk)) / sum(sum(pk .* Qpk));
|
|
phi = phi + alphak * pk;
|
|
rk = rk - alphak * Qpk;
|
|
|
|
% check the stopping conditions
|
|
if ((k >= numel(psi)) || (norm(rk(:)) < eps * normR0)) break; end;
|
|
end
|
|
end
|
|
end
|
|
|
|
function phi = solvePoisson(rho)
|
|
% solve the poisson equation using dct
|
|
dctRho = dct2(rho);
|
|
[N, M] = size(rho);
|
|
[I, J] = meshgrid([0:M-1], [0:N-1]);
|
|
dctPhi = dctRho ./ 2 ./ (cos(pi*I/M) + cos(pi*J/N) - 2);
|
|
dctPhi(1,1) = 0; % handling the inf/nan value
|
|
|
|
% now invert to get the result
|
|
phi = idct2(dctPhi);
|
|
|
|
end
|
|
|
|
% apply the transformation (A^T)(W^T)(W)(A) to 2D matrix
|
|
function Qp = applyQ(p, WW)
|
|
% apply (A)
|
|
dx = [diff(p, 1, 2), zeros([size(p,1),1])];
|
|
dy = [diff(p, 1, 1); zeros([1,size(p,2)])];
|
|
|
|
% apply (W^T)(W)
|
|
WWdx = WW .* dx;
|
|
WWdy = WW .* dy;
|
|
|
|
% apply (A^T)
|
|
WWdx2 = [zeros([size(p,1),1]), WWdx];
|
|
WWdy2 = [zeros([1,size(p,2)]); WWdy];
|
|
Qp = diff(WWdx2,1,2) + diff(WWdy2,1,1);
|
|
end
|