Why does imhist() do this?
I thought I had asked this once before, but maybe it was a fever dream. It’s hard to tell at this point.
IPT imhist() is a convenience tool for creating histograms of grayscale image data. It bins the image data such that the end bins are centered on the ends of the interval implied by the numeric class of the data (e.g. [0 1] for ‘double’). It displays the histogram using a stem() plot, with one stem in the center of each histogram bin.
This much might be disagreeable, since the end bins are effectively half-width, but let’s accept the choice to align the bin centers to the interval limits instead of aligning the bin edges.
What I can’t understand is the colorbar. Beneath the stem plot is a grayscale colorbar showing the progression N gray levels corresponding to the N histogram bins. The problem is twofold:
While the histogram bin centers are aligned to the interval limits (and cannot be changed), the gray segments of the colorbar have their edges aligned with the interval limits — and they can’t be changed either. The two are always misaligned.
The actual gray values used in the colorbar correspond to the upper edge of where the histogram bins would be if they were edge-aligned, but they’re not. The first half of the gray segments don’t even correspond to the bin they represent. The asymmetry makes plots with small N extra nonsensical.
So I put together a thing for visual emphasis and figured I’d run it here to see if it’s just my old version. It’s not.
% some inputs
inpict = rand(500);
n = 5;
% imhist can either give outputs or plot.
% it can’t do both, so we have to call it twice.
imhist(inpict,n); hold on
[counts centers] = imhist(inpict,n);
% find the axes since it won’t give them to us
hax = findobj(get(gcf,’children’),’type’,’axes’);
% figure out the bin edges from the centers,
% since it won’t give us edges either
dx = diff(centers(1:2));
xr = [centers(1)-dx/2 centers(end)+dx/2];
yr = ylim(hax(2));
% create two images:
% top is a smooth sweep from black to white.
% bottom corresponds to the center of each histogram bin.
% the two images should periodically match at each bin center.
smoothramp = repmat(linspace(xr(1),xr(2),100),[1 1 3]);
binramp = repmat(centers.’,[1 1 3]);
binramp = imresize(binramp,[1 size(smoothramp,2)],’nearest’);
% put an image behind the stem plot
hi = image(xr,yr,[binramp; smoothramp],’parent’,hax(2));
uistack(hi,’bottom’)
% find the stem plot and make it fat so it’s easier to see
hst = findobj(hax(2),’type’,’stem’);
set(hst,’linewidth’,3)
% draw a solid gray circle above each stem,
% such that the circle color is taken directly from the stem position
for k = 1:n
hp = plot(hax(2),centers(k),yr(2)*0.67,’.’);
hp.Color = [1 1 1]*centers(k);
hp.MarkerSize = 60;
end
So we have a stem plot, two images, and circular plot markers that all agree, but the color bar is off doing its own thing. The gray level in the first two colorbar segments isn’t even in the corresponding histogram bin.
Apparently this is the way imhist() has done it for at least the last 15 years, so is there actually a reason for it, or is it just one of those forever-bugs?
I’m in the middle of trying to write my way around MIMT’s usage of imhist(), and I’m inclined to just take a step back and make a complete replacement instead.I thought I had asked this once before, but maybe it was a fever dream. It’s hard to tell at this point.
IPT imhist() is a convenience tool for creating histograms of grayscale image data. It bins the image data such that the end bins are centered on the ends of the interval implied by the numeric class of the data (e.g. [0 1] for ‘double’). It displays the histogram using a stem() plot, with one stem in the center of each histogram bin.
This much might be disagreeable, since the end bins are effectively half-width, but let’s accept the choice to align the bin centers to the interval limits instead of aligning the bin edges.
What I can’t understand is the colorbar. Beneath the stem plot is a grayscale colorbar showing the progression N gray levels corresponding to the N histogram bins. The problem is twofold:
While the histogram bin centers are aligned to the interval limits (and cannot be changed), the gray segments of the colorbar have their edges aligned with the interval limits — and they can’t be changed either. The two are always misaligned.
The actual gray values used in the colorbar correspond to the upper edge of where the histogram bins would be if they were edge-aligned, but they’re not. The first half of the gray segments don’t even correspond to the bin they represent. The asymmetry makes plots with small N extra nonsensical.
So I put together a thing for visual emphasis and figured I’d run it here to see if it’s just my old version. It’s not.
% some inputs
inpict = rand(500);
n = 5;
% imhist can either give outputs or plot.
% it can’t do both, so we have to call it twice.
imhist(inpict,n); hold on
[counts centers] = imhist(inpict,n);
% find the axes since it won’t give them to us
hax = findobj(get(gcf,’children’),’type’,’axes’);
% figure out the bin edges from the centers,
% since it won’t give us edges either
dx = diff(centers(1:2));
xr = [centers(1)-dx/2 centers(end)+dx/2];
yr = ylim(hax(2));
% create two images:
% top is a smooth sweep from black to white.
% bottom corresponds to the center of each histogram bin.
% the two images should periodically match at each bin center.
smoothramp = repmat(linspace(xr(1),xr(2),100),[1 1 3]);
binramp = repmat(centers.’,[1 1 3]);
binramp = imresize(binramp,[1 size(smoothramp,2)],’nearest’);
% put an image behind the stem plot
hi = image(xr,yr,[binramp; smoothramp],’parent’,hax(2));
uistack(hi,’bottom’)
% find the stem plot and make it fat so it’s easier to see
hst = findobj(hax(2),’type’,’stem’);
set(hst,’linewidth’,3)
% draw a solid gray circle above each stem,
% such that the circle color is taken directly from the stem position
for k = 1:n
hp = plot(hax(2),centers(k),yr(2)*0.67,’.’);
hp.Color = [1 1 1]*centers(k);
hp.MarkerSize = 60;
end
So we have a stem plot, two images, and circular plot markers that all agree, but the color bar is off doing its own thing. The gray level in the first two colorbar segments isn’t even in the corresponding histogram bin.
Apparently this is the way imhist() has done it for at least the last 15 years, so is there actually a reason for it, or is it just one of those forever-bugs?
I’m in the middle of trying to write my way around MIMT’s usage of imhist(), and I’m inclined to just take a step back and make a complete replacement instead. I thought I had asked this once before, but maybe it was a fever dream. It’s hard to tell at this point.
IPT imhist() is a convenience tool for creating histograms of grayscale image data. It bins the image data such that the end bins are centered on the ends of the interval implied by the numeric class of the data (e.g. [0 1] for ‘double’). It displays the histogram using a stem() plot, with one stem in the center of each histogram bin.
This much might be disagreeable, since the end bins are effectively half-width, but let’s accept the choice to align the bin centers to the interval limits instead of aligning the bin edges.
What I can’t understand is the colorbar. Beneath the stem plot is a grayscale colorbar showing the progression N gray levels corresponding to the N histogram bins. The problem is twofold:
While the histogram bin centers are aligned to the interval limits (and cannot be changed), the gray segments of the colorbar have their edges aligned with the interval limits — and they can’t be changed either. The two are always misaligned.
The actual gray values used in the colorbar correspond to the upper edge of where the histogram bins would be if they were edge-aligned, but they’re not. The first half of the gray segments don’t even correspond to the bin they represent. The asymmetry makes plots with small N extra nonsensical.
So I put together a thing for visual emphasis and figured I’d run it here to see if it’s just my old version. It’s not.
% some inputs
inpict = rand(500);
n = 5;
% imhist can either give outputs or plot.
% it can’t do both, so we have to call it twice.
imhist(inpict,n); hold on
[counts centers] = imhist(inpict,n);
% find the axes since it won’t give them to us
hax = findobj(get(gcf,’children’),’type’,’axes’);
% figure out the bin edges from the centers,
% since it won’t give us edges either
dx = diff(centers(1:2));
xr = [centers(1)-dx/2 centers(end)+dx/2];
yr = ylim(hax(2));
% create two images:
% top is a smooth sweep from black to white.
% bottom corresponds to the center of each histogram bin.
% the two images should periodically match at each bin center.
smoothramp = repmat(linspace(xr(1),xr(2),100),[1 1 3]);
binramp = repmat(centers.’,[1 1 3]);
binramp = imresize(binramp,[1 size(smoothramp,2)],’nearest’);
% put an image behind the stem plot
hi = image(xr,yr,[binramp; smoothramp],’parent’,hax(2));
uistack(hi,’bottom’)
% find the stem plot and make it fat so it’s easier to see
hst = findobj(hax(2),’type’,’stem’);
set(hst,’linewidth’,3)
% draw a solid gray circle above each stem,
% such that the circle color is taken directly from the stem position
for k = 1:n
hp = plot(hax(2),centers(k),yr(2)*0.67,’.’);
hp.Color = [1 1 1]*centers(k);
hp.MarkerSize = 60;
end
So we have a stem plot, two images, and circular plot markers that all agree, but the color bar is off doing its own thing. The gray level in the first two colorbar segments isn’t even in the corresponding histogram bin.
Apparently this is the way imhist() has done it for at least the last 15 years, so is there actually a reason for it, or is it just one of those forever-bugs?
I’m in the middle of trying to write my way around MIMT’s usage of imhist(), and I’m inclined to just take a step back and make a complete replacement instead. imhist, histogram MATLAB Answers — New Questions