-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathphase_unwrap_Ghiglia.m
More file actions
100 lines (84 loc) · 3.6 KB
/
phase_unwrap_Ghiglia.m
File metadata and controls
100 lines (84 loc) · 3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 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_Ghiglia(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-8;
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;
GradDsct
% 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