1## Copyright (C) 2008 Søren Hauberg <soren@hauberg.org>
2##
3## This program is free software; you can redistribute it and/or modify it under
4## the terms of the GNU General Public License as published by the Free Software
5## Foundation; either version 3 of the License, or (at your option) any later
6## version.
7##
8## This program is distributed in the hope that it will be useful, but WITHOUT
9## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11## details.
12##
13## You should have received a copy of the GNU General Public License along with
14## this program; if not, see <http://www.gnu.org/licenses/>.
15
16## -*- texinfo -*-
17## @deftypefn {Function File} {} imclose (@var{img}, @var{SE})
18## Perform morphological closing.
19##
20## The matrix @var{img} must be numeric while @var{SE} can be a:
21## @itemize @bullet
22## @item
23## strel object;
24## @item
25## array of strel objects as returned by `@@strel/getsequence';
26## @item
27## matrix of 0's and 1's.
28## @end itemize
29##
30## The closing corresponds to a dilation followed by an erosion of @var{img},
31## using the same @var{SE}, i.e., it is equivalent to:
32## @example
33## imerode (imdilate (img, se), se);
34## @end example
35##
36## @seealso{imdilate, imerode, imopen}
37## @end deftypefn
38
39function closed = imclose (img, se)
40
41  if (nargin != 2)
42    print_usage ();
43  elseif (! isimage (img))
44    error("imclose: IMG must be a numeric matrix");
45  endif
46  se = prepare_strel ("imclose", se);
47
48  ## Perform filtering
49  closed = imerode (imdilate (img, se), se);
50
51endfunction
52
53%!shared in, out
54%! in =  [ 0   0   0   1   1   1   0   0   1   1
55%!       0   1   0   1   1   1   0   0   0   1
56%!       1   1   1   1   1   0   0   0   0   0
57%!       0   1   1   1   1   0   0   0   0   0
58%!       0   0   0   1   0   0   0   0   1   0
59%!       0   0   0   0   0   0   0   1   1   1
60%!       0   0   0   0   1   0   1   0   1   0
61%!       0   0   0   1   1   1   1   1   0   0
62%!       0   0   0   0   1   1   1   0   0   0
63%!       0   0   0   1   1   1   0   0   0   0];
64%!
65%! out = [ 1   1   1   1   1   1   1   1   1   1
66%!       1   1   1   1   1   1   0   0   0   1
67%!       1   1   1   1   1   0   0   0   0   1
68%!       1   1   1   1   1   0   0   0   0   1
69%!       0   0   0   1   1   0   0   0   1   1
70%!       0   0   0   1   1   1   1   1   1   1
71%!       0   0   0   1   1   1   1   1   1   1
72%!       0   0   0   1   1   1   1   1   0   0
73%!       0   0   0   1   1   1   1   0   0   0
74%!       0   0   0   1   1   1   1   0   0   0];
75%!assert (imclose (logical (in), ones (3)), logical (out));
76%!
77%! out = [99   99   16   16   16   73   74   64   64   64
78%!      98   88   16   16   16   73   71   64   64   64
79%!      93   88   88   61   61   61   68   70   70   70
80%!      93   88   88   61   61   61   68   71   71   71
81%!      93   93   88   61   61   61   68   75   66   66
82%!      79   79   82   90   90   49   49   49   49   66
83%!      79   79   82   91   91   48   46   46   46   66
84%!      79   79   82   95   97   48   46   46   46   72
85%!      18   18   94   96   84   48   46   46   46   59
86%!      18   18  100   96   84   50   50   50   50   59];
87%!assert (imclose (magic (10), ones (3)), out);
88%!assert (imclose (uint8 (magic (10)), strel ("square", 3)), uint8 (out));
89%!
90%! ## using a se that will be decomposed in 2 pieces
91%! out =[ 99   99   88   74   74   74   74   70   70   70
92%!        98   93   88   74   74   74   74   70   70   70
93%!        93   93   88   74   74   74   74   70   70   70
94%!        93   93   88   74   74   74   74   71   71   71
95%!        93   93   88   75   75   75   75   75   75   75
96%!        93   93   90   90   90   72   72   72   72   72
97%!        93   93   91   91   91   72   72   72   72   72
98%!        93   93   93   95   97   72   72   72   72   72
99%!        94   94   94   96   97   72   72   72   72   72
100%!       100  100  100   97   97   72   72   72   72   72];
101%!assert (imclose (magic (10), ones(5)), out);
102%!
103%! ## using a weird non-symmetric and even-size se
104%! out =[ 92   99   16   16   16   70   74   58   58   58
105%!        98   88   60   73   16   73   69   70   64   58
106%!        88   81   88   60   60   60   69   69   70   70
107%!        87   87   61   68   61   60   68   69   71   69
108%!        86   93   87   61   61   61   68   75   68   69
109%!        23   82   89   89   90   45   68   45   68   66
110%!        23   23   82   89   91   48   45   45   45   66
111%!        79   23   82   95   97   46   48   46   45   72
112%!        18   79   94   96   78   50   46   46   46   59
113%!        18   18  100   94   94   78   50   50   46   59];
114%!assert (imclose (magic (10), [1 0 0 0; 1 1 1 0; 0 1 0 1]), out);
115