Mercurial > hg > octave-image
view inst/imhist.m @ 640:19907cddd83a
graythresh: fix bug on mean method (unitialized variable), use mean on otsu's methdo when multiple max values, add tests
author | carandraug |
---|---|
date | Mon, 01 Oct 2012 15:49:46 +0000 |
parents | 41c917791057 |
children | 372346150564 |
line wrap: on
line source
## Copyright (C) 2011, 2012 Carnë Draug <carandraug+dev@gmail.com> ## ## This program is free software; you can redistribute it and/or modify it under ## the terms of the GNU General Public License as published by the Free Software ## Foundation; either version 3 of the License, or (at your option) any later ## version. ## ## This program is distributed in the hope that it will be useful, but WITHOUT ## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ## details. ## ## You should have received a copy of the GNU General Public License along with ## this program; if not, see <http://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} imhist (@var{I}) ## @deftypefnx {Function File} {} imhist (@var{I}, @var{n}) ## @deftypefnx {Function File} {} imhist (@var{X}, @var{cmap}) ## @deftypefnx {Function File} {[@var{counts}, @var{x}] =} imhist (@dots{}) ## Produce histogram counts of image @var{I}. ## ## The second argument can either be @var{n}, a scalar that specifies the number ## of bins; or @var{cmap}, a colormap in which case @var{X} is expected to be ## an indexed image. If not specified, @var{n} defauls to 2 for binary images, ## and 256 for grayscale images. ## ## If output is requested, @var{counts} is the number of counts for each bin and ## @var{x} is a range for the bins so that @code{stem (@var{x}, @var{counts})} will ## show the histogram. ## ## Since a colorbar is not displayed under the histogram, calling this function ## to visualize the histogram of an indexed image may not be very helpful. ## ## @seealso{hist, histc, histeq} ## @end deftypefn function [varargout] = imhist (img, b) ## then img can either be a "normal" or indexed image. We will need to ## check the second argument to find out indexed = false; if (nargin < 1 || nargin > 2) print_usage; elseif (nargin == 1) if (islogical (img)) b = 2; else b = 256; endif elseif (nargin == 2) if (iscolormap (b)) ## if using a colormap, image must be an indexed image indexed = true; elseif (isnumeric (b) && isscalar (b) && fix(b) == b) ## do nothing, all is good if (islogical (img) && b != 2) error ("there can only be 2 bins when input image is binary") endif else error ("second argument should either be a positive integer scalar or a colormap"); endif endif ## check if img is good if (indexed) if (!isind(img)) error ("second argument is a colormap but image is not indexed"); endif ## an indexed image reads differently wether it's uint8/16 or double ## If uint8/16, index-1 is the colormap row number (there's an offset of 1) ## If double, index is the colormap row number (no offset) ## isind above already checks for double/uint8/uint16 so we can use isinteger ## and isfloat safely if ( (isfloat (img) && max (img(:)) > rows(b) ) || (isinteger (img) && max (img(:)) > rows(b)-1) ) warning ("largest index in image exceeds length of colormap"); endif endif ## prepare bins if (indexed) if (isinteger (img)) bins = 0:rows(b)-1; else bins = 1:rows(b); endif else if (isinteger (img)) bins = linspace (intmin (class (img)), intmax (class (img)), b); elseif (islogical (img)) bins = 0:1; else ## image must be single or double bins = linspace (0, 1, b); endif ## we will use this bins with histc where they are the edges for each bin ## but in imhist we want them to be the center of each bin. We can't use ## hist either since values right in the middle will go to the bottom ## bin (4.5 will be placed on the bin 4 instead of 5 and this is like ## matlab, not an octave bug). So we still use histc but we decrease their ## values by half of bin width and increase it back in the end to return ## the values (if we did it on the image it would be only one step but ## would be heavier on the system since images are likely to be larger ## than bins) if (!islogical (img)) bins -= ((bins(2) - bins(1))/2); endif ## matlab returns bins as one column instead of a row but only for non ## indexed images bins = bins'; endif ## if not dealing with indexed image, we may need to make sure values are ## between get bin values if (!indexed) ## while integers could in no way have a value below the minium of their ## class, floats can have values below zero which need to be truncated if (isfloat (img)) img(img < 0) = 0; endif ## because we adjusted the bins edge below the max value of the class, and ## because histc will not count values outside the edges, we need to bring ## them down (no need to worry about the min because the min edge is already ## below the mininum of the class). This also adjusts floats above 1 if (max (img(:)) > bins(end)) ## in case it's a integer, if we try to assign the non integer values it ## will fail so we need to make it double. But this means it takes more ## memory so let's first make sure we need to if (fix(bins(end)) != bins(end)) img = double (img); endif img(img > bins(end)) = bins(end); endif endif [nn] = histc (img(:), bins); if (!indexed && !islogical(img)) bins += ((bins(2) - bins(1))/2); endif if (nargout != 0) varargout{1} = nn; varargout{2} = bins; else hold on; stem (bins, nn); colormap (gray (b)); colorbar ("SouthOutside", "xticklabel", []); hold off; endif endfunction %!shared nn, bb, enn, ebb %! [nn, bb] = imhist(logical([0 1 0 0 1])); %!assert({nn, bb}, {[3 2]', [0 1]'}) %! [nn, bb] = imhist([0 0.2 0.4 0.9 1], 5); %!assert({nn, bb}, {[1 1 1 0 2]', [0 0.25 0.5 0.75 1]'}) %! [nn, bb] = imhist([-2 0 0.2 0.4 0.9 1 5], 5); %!assert({nn, bb}, {[2 1 1 0 3]', [0 0.25 0.5 0.75 1]'}) %! [nn, bb] = imhist(uint8([0 32 255]), 256); %! enn = zeros(256, 1); enn([1, 33, 256]) = 1; %! ebb = 0:255; %!assert({nn, bb}, {enn, ebb'}) %! [nn, bb] = imhist(int8([-50 0 100]), 31); %! enn = zeros(31, 1); enn([10, 16, 28]) = 1; %! ebb = -128:8.5:127; %!assert({nn, bb}, {enn, ebb'})