-
Notifications
You must be signed in to change notification settings - Fork 73
/
laplacefill.m
104 lines (87 loc) · 3.14 KB
/
laplacefill.m
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
101
102
103
104
function newvol = laplacefill(vol, seeds, solver, tol, maxiter, varargin)
%
% newvol = laplacefill(vol, seeds, solver, tol, maxiter, ...)
%
% perform a hole-fill or flood-fill in a 2-D or 3-D binary image using
% Laplace solver
%
% author: Qianqian Fang, <q.fang at neu.edu>
%
% input:
% vol: a 2-D or 3-D binary image
% seeds: seeds for flood-fill, 2 or 3-column matrix; if empty, perfrom
% hole-fill
% solver: (optional) linear solver, if not given, use bicgstab
% tol: (optional) linear solver convergence tolerance, default 1e-5
% maxiter: (optional) linear solver max iteration, default 3000
%
% additional parameters that are supported by any iterative solver,
% such as qmr, pcg, gmres, tfqmr, mldivide, minres etc
%
% output:
% newvol: the volume image after flood-fill or hole-fill
%
% example:
% a = zeros(60, 80, 90);
% a(20:40, 40:70, 30:80)=1;
% a(25:35, 50:60, 50:60)=0;
% newvol = laplacefill(a);
%
% -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
%
dims = size(vol) + 2;
interiornode = prod(dims - 2);
zeroidx = find(vol == 0);
if (ndims(vol) == 3)
[ix, iy, iz] = ndgrid(2:dims(1) - 1, 2:dims(2) - 1, 2:dims(3) - 1);
else
[ix, iy, iz] = ndgrid(2:dims(1) - 1, 2:dims(2) - 1, 2);
dims(3) = 3;
end
ix = ix(zeroidx);
iy = iy(zeroidx);
iz = iz(zeroidx);
idx = sub2ind(dims - 2, ix - 1, iy - 1, iz - 1); % index of all interior nodes in the subset of interior nodes
idx = idx(:)';
nnzpos = {idx, idx(ix > 2), idx(ix < dims(1) - 1), idx(iy > 2), idx(iy < dims(2) - 1), idx(iz > 2), idx(iz < dims(3) - 1)};
nonzeroidx = find(vol > 0)';
seedidx = [];
if (nargin > 1 && size(seeds, 2) == 3)
seedidx = sub2ind(dims(1:3) - 2, seeds(:, 1), seeds(:, 2), seeds(:, 3));
end
Amat = sparse([seedidx, nonzeroidx, nnzpos{1}, nnzpos{2} - 1, nnzpos{3} + 1, ...
nnzpos{4} - dims(1) + 2, nnzpos{5} + dims(1) - 2, ...
nnzpos{6} - (dims(1) - 2) * (dims(2) - 2), nnzpos{7} + (dims(1) - 2) * (dims(2) - 2)], ...
[seedidx, nonzeroidx, nnzpos{:}], ...
[ones(1, length(seedidx)) ones(1, length(nonzeroidx)) -ones(1, length(idx)) ...
(1 / 6) * ones(1, sum(cellfun(@(x) length(x), nnzpos(2:end))))], ...
interiornode, interiornode);
if (~isempty(seedidx))
b = sparse(seedidx, ones(size(seedidx)), ones(size(seedidx)), interiornode, 1);
else
if (ndims(vol) == 3)
boundnode = idx(ix == 2 | iy == 2 | iz == 2 | ix == dims(1) - 1 | iy == dims(2) - 1 | iz == dims(3) - 1);
else
boundnode = idx(ix == 2 | iy == 2 | ix == dims(1) - 1 | iy == dims(2) - 1);
end
b = sparse(boundnode, ones(size(boundnode)), -(1 / 6) * ones(size(boundnode)), interiornode, 1);
end
if (nargin < 4)
tol = 1e-10;
end
if (nargin < 5)
maxiter = 3000;
end
if (nargin > 2)
mysolver = str2func(solver);
[newvol, flag] = mysolver(Amat, b, tol, maxiter, varargin{:});
else
[newvol, flag] = bicgstab(Amat, b, tol, maxiter, varargin{:});
end
if (flag)
newvol = gmres(Amat, b, 28, tol, maxiter, varargin{:});
end
newvol = reshape(full(newvol), size(vol));
if (isempty(seedidx))
newvol = ~(newvol > tol);
end