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} {@var{E} =} entropy (@var{im})
18## @deftypefnx{Function File} {@var{E} =} entropy (@var{im}, @var{nbins})
19## Computes the entropy of an image.
20##
21## The entropy of the elements of the image @var{im} is computed as
22##
23## @example
24## @var{E} = -sum (@var{P} .* log2 (@var{P})
25## @end example
26##
27## where @var{P} is the distribution of the elements of @var{im}. The distribution
28## is approximated using a histogram with @var{nbins} cells. If @var{im} is
29## @code{logical} then two cells are used by default. For other classes 256 cells
30## are used by default.
31##
32## When the entropy is computed, zero-valued cells of the histogram are ignored.
33##
34## @seealso{entropyfilt}
35## @end deftypefn
36
37function retval = entropy (I, nbins = 0)
38  if (nargin < 1 || nargin > 2)
39    print_usage ();
40  endif
41
42  if ( (! isnumeric (I) && ! islogical (I)) || issparse (I) || (! isreal (I)) )
43    error ("entropy: I must be real, non-sparse and numeric");
44  endif
45
46  if (! isscalar (nbins))
47    error ("entropy: NBINS must be a scalar");
48  endif
49
50  ## Get number of histogram bins
51  if (nbins <= 0)
52    if (islogical (I))
53      nbins = 2;
54    else
55      nbins = 256;
56    endif
57  endif
58
59  ## transform all non-logical images to uint8 (as Matlab):
60  if (! islogical (I))
61      I = im2uint8 (I);
62  end
63
64  ## Compute histogram, using imhist (as Matlab claims to do)
65  P = imhist (I(:), nbins);
66
67  ## ignore zero-entries of the histogram, and normalize it to a sum of 1
68  P(P==0) = [];
69  P = P ./ sum (P(:));
70
71  ## Compute entropy
72  retval = -sum (P .* log2 (P));
73endfunction
74
75%!assert (entropy ([0 1]), 1)
76%!assert (entropy (uint8 ([0 1])), 1)
77%!assert (entropy ([0 0]), 0)
78%!assert (entropy ([0]), 0)
79%!assert (entropy ([1]), 0)
80%!assert (entropy ([0 .5; 2 0]), 1.5)
81
82## rgb images are treated like nd grayscale images
83%!assert (entropy (repmat ([0 .5; 2 0], 1, 1, 3)),
84%!        entropy ([0 .5; 2 0]))
85
86## test some 9x9 float input images
87%!test
88%! A = zeros (3,3);
89%! B = ones (3,3);
90%! C = [1 1 1; 2 2 2; 3 3 3];
91%! D = C';
92%! E = ones (3,3);
93%! E(2,2)=2;
94%! F = 3 .* ones (3,3);
95%! F(2,2)=1;
96%! G = [-1 2 7; -5 2 8; -7 pi 9];
97%! H = [5 2 8; 1 -3 1; 5 1 0];
98%! pG = [1 2] ./ 3;
99%! G_out = -sum (pG.*log2 (pG));
100%! pH = [2 7] ./ 9;
101%! H_out = -sum (pH.*log2 (pH));
102%! assert (entropy (A), 0, eps);
103%! assert (entropy (B), 0, eps);
104%! assert (entropy (C), 0, eps);
105%! assert (entropy (D), 0, eps);
106%! assert (entropy (E), 0, eps);
107%! assert (entropy (F), 0, eps);
108%! assert (entropy (G), G_out, eps);
109%! assert (entropy (H), H_out, eps);
110
111## test some 9x9 uint8 input images
112%!test
113%! A = uint8 (zeros (3,3));
114%! B = uint8 (ones (3,3));
115%! C = uint8 ([1 1 1; 2 2 2; 3 3 3]);
116%! D = C';
117%! E = uint8 (ones (3,3));
118%! E(2,2)=2;
119%! F = 3 .* uint8 (ones (3,3));
120%! F(2,2)=1;
121%! G = uint8 ([0 2 7; 0 2 8; 0 3 9]);
122%! H = uint8 ([5 2 8; 1 0 1; 5 1 0]);
123%! pC = [1 1 1] ./ 3;
124%! C_out = -sum (pC.*log2 (pC));
125%! D_out = C_out;
126%! pE = [8 1] ./ 9;
127%! E_out = -sum (pE.*log2 (pE));
128%! F_out = E_out;
129%! pG = [3 2 1 1 1 1] ./ 9;
130%! G_out = -sum (pG.*log2 (pG));
131%! pH = [2 3 1 2 1] ./ 9;
132%! H_out = -sum (pH.*log2 (pH));
133%! assert (entropy (A), 0);
134%! assert (entropy (B), 0);
135%! assert (entropy (C), C_out, eps);
136%! assert (entropy (D), D_out, eps);
137%! assert (entropy (E), E_out, eps);
138%! assert (entropy (F), F_out, eps);
139%! assert (entropy (G), G_out, eps);
140%! assert (entropy (H), H_out, eps);
141
142## test some 9x9 logical input images
143%!test
144%! L1 = false (3,3);
145%! L1(2,2)=true;
146%! L2 = true (3,3);
147%! L2(2,2)=false;
148%! L3 = logical ([0 1 1; 0 1 1; 0 0 1]);
149%! p12 = [1 8] ./ 9;
150%! out12 = -sum (p12.*log2 (p12));
151%! p3 = [5 4] ./9;
152%! out3 = -sum (p3.*log2 (p3));
153%! assert (entropy (L1), out12, eps);
154%! assert (entropy (L2), out12, eps);
155%! assert (entropy (L3), out3, eps);
156