changeset 11233:7a95ad6a35fa octave-forge

imhist: bugfix and nicer plot * remove marker from top of stem * scale x axis properly so that colorbar is correct * use given colormap for indexed images * make sure that number of bins is a positive number * rewrite long complicated comments * remove note from help text about not displaying colorbar
author carandraug
date Sun, 11 Nov 2012 02:32:41 +0000
parents 414e05bfdab3
children f31a074baf3c
files main/image/NEWS main/image/inst/imhist.m
diffstat 2 files changed, 61 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/main/image/NEWS	Fri Nov 09 15:07:58 2012 +0000
+++ b/main/image/NEWS	Sun Nov 11 02:32:41 2012 +0000
@@ -1,3 +1,11 @@
+Summary of important user-visible changes for image 2.0.1:
+-------------------------------------------------------------------
+
+ ** The plot produced by `imhist' is correctly scaled on the X axis so that the
+    colorbar corresponds to the actual intensity of the stems; the given
+    colormarp is used on the colorbar for indexed images; and the stems no
+    longer display the markers at their top.
+
 Summary of important user-visible changes for image 2.0.0:
 -------------------------------------------------------------------
 
--- a/main/image/inst/imhist.m	Fri Nov 09 15:07:58 2012 +0000
+++ b/main/image/inst/imhist.m	Sun Nov 11 02:32:41 2012 +0000
@@ -14,7 +14,7 @@
 ## this program; if not, see <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} imhist (@var{I})
+## @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{})
@@ -29,16 +29,12 @@
 ## @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
+  ## "img" can be a normal or indexed image. We need to check "b" to find out
   indexed = false;
 
   if (nargin < 1 || nargin > 2)
@@ -53,35 +49,30 @@
 
   elseif (nargin == 2)
     if (iscolormap (b))
-      ## if using a colormap, image must be an indexed image
+      if (!isind(img))
+        error ("imhist: second argument is a colormap but first argument is not an indexed image.");
+      endif
       indexed = true;
-    elseif (isnumeric (b) && isscalar (b) && fix(b) == b)
-      ## do nothing, all is good
+      ## an indexed image reads differently wether it's uint8/16 or double
+      ## If uint8/16, index+1 is the colormap row number (0 on the image
+      ## corresponds to the 1st column on the colormap).
+      ## 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 ("imhist: largest index in image exceeds length of colormap.");
+      endif
+    elseif (isnumeric (b) && isscalar (b) && fix(b) == b && b > 0)
       if (islogical (img) && b != 2)
-        error ("there can only be 2 bins when input image is binary")
+        error ("imhist: 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");
+      error ("imhist: second argument must 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
+  ## prepare bins and image
   if (indexed)
     if (isinteger (img))
       bins = 0:rows(b)-1;
@@ -97,48 +88,49 @@
       ## 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)
+    ## we will use this bins with histc() where their values will be edges for
+    ## each bin. However, what we actually want is for their values to be the
+    ## center of each bin. To do this, we decrease their values by half of bin
+    ## width and will increase it back at the end of the function. We could do
+    ## it on the image and it would be a single step but it would be an heavier
+    ## operation since images are likely to be much longer than the bins.
+    ## The use of hist() is also not simple for this since values right in the
+    ## middle of two bins will go to the bottom bin (4.5 will be placed on the
+    ## bin 4 instead of 5 and we must keep matlab compatibility).
+    ## Of course, none of this needed for binary images.
     if (!islogical (img))
-      bins -= ((bins(2) - bins(1))/2);
+      bins_adjustment = ((bins(2) - bins(1))/2);
+      bins -= bins_adjustment;
     endif
     ## matlab returns bins as one column instead of a row but only for non
     ## indexed images
     bins = bins';
-  endif
+
+    ## histc does not counts values outside the edges of the bins so we need to
+    ## truncate their values.
 
-  ## 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))
+    ## truncate the minimum... integers could in no way have a value below the
+    ## minimum of their class so truncation on this side is only required for
+    if (isfloat (img) && min (img(:)) < 0)
       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
+
+    ## truncating the maximum... also adjusts floats above 1. We might need
     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))
+      ## bins (end) is probably a decimal number. If an image is an int, we
+      ## can't assign the new value since it will be fix(). So we need to change
+      ## the image class to double but that will take more memory so let's
+      ## avoid it if we can
+      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);
+    bins += bins_adjustment;
   endif
 
   if (nargout != 0)
@@ -146,8 +138,13 @@
     varargout{2} = bins;
   else
     hold on;
-    stem (bins, nn);
-    colormap (gray (b));
+    stem (bins, nn, "marker", "none");
+    xlim ([bins(1) bins(end)]);
+    if (indexed)
+      colormap (b);
+    else
+      colormap (gray (b));
+    endif
     colorbar ("SouthOutside", "xticklabel", []);
     hold off;
   endif