1## Copyright (C) 2000 Kai Habel <kai.habel@gmx.de> 2## Copyright (C) 2012-2016 Carnë Draug <carandraug@octave.org> 3## 4## This program is free software; you can redistribute it and/or 5## modify it under the terms of the GNU General Public License as 6## published by the Free Software Foundation; either version 3 of the 7## License, or (at your option) any later version. 8## 9## This program is distributed in the hope that it will be useful, but 10## WITHOUT ANY WARRANTY; without even the implied warranty of 11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12## General Public License for more details. 13## 14## You should have received a copy of the GNU General Public License 15## along with this program; if not, see 16## <http:##www.gnu.org/licenses/>. 17 18## -*- texinfo -*- 19## @deftypefn {Function File} {} im2bw (@var{img}) 20## @deftypefnx {Function File} {} im2bw (@var{X}, @var{cmap}) 21## @deftypefnx {Function File} {} im2bw (@dots{}, @var{threshold}) 22## @deftypefnx {Function File} {} im2bw (@dots{}, @var{method}) 23## Convert image to binary, black and white, by threshold. 24## 25## The input image @var{img} can either be a grayscale or RGB image. In the later 26## case, @var{img} is first converted to grayscale with @code{rgb2gray}. Input 27## can also be an indexed image @var{X} in which case the colormap @var{cmap} 28## needs to be specified. 29## 30## The value of @var{threshold} should be in the range [0,1] independently of the 31## class of @var{img}. Values from other classes can be converted to the correct 32## value with @code{im2double}: 33## 34## @example 35## bw = im2bw (img_of_class_uint8, im2double (thresh_of_uint8_class)); 36## @end example 37## 38## For an automatic threshold value, consider using @code{graythresh}. 39## The argument @var{method} is a string that specifies a valid algorithm 40## available in @code{graythresh}. The following are equivalent: 41## 42## @example 43## bw = im2bw (img, "moments"); 44## bw = im2bw (img, graythresh (img, "moments")); 45## @end example 46## 47## @seealso{graythresh, ind2gray, otsuthresh, rgb2gray} 48## @end deftypefn 49 50function BW = im2bw (img, cmap, thresh = 0.5) 51 52 if (nargin < 1 || nargin > 3) 53 print_usage (); 54 elseif (nargin == 3 && ! isind (img)) 55 error ("im2bw: IMG must be an indexed image when are 3 input arguments"); 56 elseif (nargin == 3 && ! iscolormap (cmap)) 57 error ("im2bw: CMAP must be a colormap"); 58 elseif (nargin == 2) 59 thresh = cmap; 60 endif 61 62 if (! isimage (img)) 63 error ("im2bw: IMG must be an image"); 64 elseif (! ischar (thresh) && ! (isnumeric (thresh) && isscalar (thresh) 65 && thresh >= 0 && thresh <= 1)) 66 error ("im2bw: THRESHOLD must be a string or a scalar in the interval [0 1]"); 67 endif 68 69 if (islogical (img)) 70 warning ("im2bw: IMG is already binary so nothing is done"); 71 tmp = img; 72 73 else 74 ## Convert img to gray scale 75 if (nargin == 3) 76 ## indexed image (we already checked that is indeed indexed earlier) 77 img = ind2gray (img, cmap); 78 elseif (isrgb (img)) 79 img = rgb2gray (img); 80 else 81 ## Everything else, we do nothing, no matter how many dimensions 82 endif 83 84 if (ischar (thresh)) 85 thresh = graythresh (img, thresh); 86 endif 87 88 ## Convert the threshold value to same class as the image which 89 ## is faster and saves more memory than the opposite. 90 if (isinteger (img)) 91 ## We do the conversion from double to int ourselves (instead 92 ## of using im2uint* functions), because those functions round 93 ## during the conversion but we need thresh to be the limit. 94 ## See bug #46390. 95 cls = class(img); 96 I_min = double (intmin (cls)); 97 I_range = double (intmax (cls)) - I_min; 98 thresh = cast (floor ((thresh * I_range) + I_min), cls); 99 elseif (isfloat (img)) 100 ## do nothing 101 else 102 ## we should have never got here in the first place anyway 103 error ("im2bw: unsupported image of class '%s'", class (img)); 104 endif 105 106 tmp = (img > thresh); 107 endif 108 109 if (nargout > 0) 110 BW = tmp; 111 else 112 imshow (tmp); 113 endif 114 115endfunction 116 117%!assert(im2bw ([0 0.4 0.5 0.6 1], 0.5), logical([0 0 0 1 1])); # basic usage 118%!assert(im2bw (uint8 ([0 100 255]), 0.5), logical([0 0 1])); # with a uint8 input 119 120## We use "bw = im2bw (...)" because otherwise it would display a figure 121%!warning <is already binary so nothing is done> bw = im2bw (logical ([0 1 0])); 122%!warning <is already binary so nothing is done> bw = im2bw (logical ([0 1 0]), 1); 123 124%!test 125%! warning ("off", "all", "local"); 126%! assert (im2bw (logical ([0 1 0])), logical ([0 1 0])) 127%! assert (im2bw (logical ([0 1 0]), 0), logical ([0 1 0])) 128%! assert (im2bw (logical ([0 1 0]), 1), logical ([0 1 0])) 129 130## bug #46390 (on the rounding/casting of the threshold value) 131%!assert (nnz (im2bw (uint8 ([0:255]), 0.9)), 26) 132 133%!test 134%! img = uint8 ([0:255]); 135%! s = 0; 136%! for i=0:.1:1 137%! s += nnz (im2bw (img, i)); 138%! endfor 139%! assert (s, 1405) 140 141## threshold may be a negative value in the image class so care must 142## taken when casting and rounding it. 143%!assert (nnz (im2bw (int16 ([-128:127]), 0.499)), 194) 144%!assert (nnz (im2bw (int16 ([-128:127]), 0.500)), 128) 145%!assert (nnz (im2bw (int16 ([-128:127]), 0.501)), 62) 146 147%!test 148%! img = uint16 ([0:intmax("uint16")]); 149%! s = 0; 150%! for i=0:.1:1 151%! s += nnz (im2bw (img, i)); 152%! endfor 153%! assert (s, 360445) 154 155%!test 156%! img = int16 ([intmin("int16"):intmax("int16")]); 157%! s = 0; 158%! for i=0:.1:1 159%! s += nnz (im2bw (img, i)); 160%! endfor 161%! assert (s, 360445) 162 163%!test 164%! im = [((randn(10)/10)+.3) ((randn(10)/10)+.7)]; 165%! assert (im2bw (im, "Otsu"), im2bw (im, graythresh (im, "Otsu"))) 166%! assert (im2bw (im, "moments"), im2bw (im, graythresh (im, "moments"))) 167 168%!test 169%! im = [((randn(10)/10)+.3) ((randn(10)/10)+.7)]; 170%! im = reshape (im, [10 10 1 2]); 171%! assert (im2bw (im, "Otsu"), im2bw (im, graythresh (im, "Otsu"))) 172%! assert (im2bw (im, "moments"), im2bw (im, graythresh (im, "moments"))) 173