1

Gnoivce and Hartmut helped a lot with this code but it takes a while to run. The CData property in the bar command doesn't seem to be implemented in the Octave 4.0-4.2.1 version which I'm using. The work around for this was to plot all the single bars individually and set an individual color for each individual bar. People helped me out and got me this far but it takes 5 minutes for the plot to show does anyone know a way of speeding this up?

The following code runs: marbles.jpg image file used below: marbles.jpg

clear all,clf reset,tic,clc 
rgbImage = imread('/tmp/marbles.jpg');
hsvImage = rgb2hsv(rgbImage);         % Convert the image to HSV space
hPlane = 360.*hsvImage(:, :, 1);      % Get the hue plane scaled from 0 to 360
binEdges = 0:360;                 %# Edges of histogram bins
N = histc(hPlane(:),binEdges);    %# Bin the pixel hues from above

C = colormap(hsv(360));  %# create an HSV color map with 360 points
stepsize = 1; % stepsize 1 runs for a while...

for n=binEdges(2:stepsize:end)   %# Plot the histogram, one bar each
    if (n==1), hold on, end
    h=bar(n,N(n));
    set(h,'FaceColor',C(n,:));   %# set the bar color individually
end

axis([0 360 0 max(N)]);           %# Change the axes limits
set(gca,'Color','k');             %# Change the axes background color
set(gcf,'Pos',[50 400 560 200]);  %# Change the figure size
xlabel('HSV hue (in degrees)');   %# Add an x label
ylabel('Bin counts');             %# Add a y label
fprintf('\nfinally Done-elapsed time -%4.4fsec- or -%4.4fmins- or -%4.4fhours-\n',toc,toc/60,toc/3600);

Plot created after 5 mins: Plot

To see original question original question

Community
  • 1
  • 1
Rick T
  • 3,349
  • 10
  • 54
  • 119
  • Have you checked which part of your code is taking so long? Is it the loop? – gnovice Apr 24 '17 at 19:15
  • @gnovice yes it's `stepsize = 1; % stepsize 1 runs for a while...` that causes the time to increase if `stepsize is set to 10` it's quicker but it leaves empty space between the bars. – Rick T Apr 24 '17 at 21:39
  • 2
    why don't you generate an image instead of the bar plot? – Andy Apr 25 '17 at 10:58
  • @Andy I'm willing to trying anything but wouldn't I still need to loop through a For loop which is causing the slow down? Or am I missing something? – Rick T Apr 25 '17 at 13:27
  • 1
    @RickT Is something missing in these two answers? If you don't accept one of them you should comment why they don't answer your question – Andy Apr 29 '17 at 08:14
  • @Andy thanks for the catch I thought I checked it but it looks like I only clicked the +1 – Rick T Apr 29 '17 at 10:48

2 Answers2

3

I'm guessing the loop is the bottleneck in your code that is taking so long? You could remove the loop and create the plot with one call to bar, then call set to modify the hggroup object and its child patch object:

h = bar(binEdges(1:end-1), N(1:end-1), 'histc');   % hggroup object
set(h, 'FaceColor', 'flat', 'EdgeColor', 'none');
hPatch = get(h, 'Children');                       % patch object
set(hPatch, 'CData', 1:360, 'CDataMapping', 'direct');

Repeating your code with this fix renders right away for me in Octave 4.0.3:

enter image description here

gnovice
  • 125,304
  • 15
  • 256
  • 359
2

As I suggested in a comment, I would use image (takes 0.12s on my system for your image).

EDIT: more comments, fix little bug, allow to create bins with stepsize > 1

img_fn = "17S9PUK.jpg";
if (! exist (img_fn, "file"))
  disp ("downloading image from imgur.com...");
  fflush (stdout);
  urlwrite ("http://i.imgur.com/17S9PUK.jpg", "17S9PUK.jpg");
endif

rgbImage = imread (img_fn);

## for debugging so the matrixes fit on screen
if (0)
  pkg load image
  rgbImage = imresize (rgbImage, [6 8]);
endif

hsvImage = rgb2hsv(rgbImage);
hPlane = 360 .* hsvImage(:, :, 1); 

## create bins, I've choosen 2 step to "smooth" the result
binEdges = 1:2:360;
N = histc (hPlane(:), binEdges)';

cm = permute (hsv (numel (binEdges)), [3 1 2]);

## Create an image with x = hue
img = repmat (cm, max(N), 1);

## Create binary mask which is used to black "img" dependent on N
sp = sparse (N(N > 0), (1:360)(N > 0), true, max(N), numel (binEdges));
mask = full (cumsum (flipud (sp)));

## extend mask in depth to suppress RGB
mask = repmat (mask, [1 1 3]);

## use inverted mask to "black out" pixels < N
img(logical (1 - flipud (mask))) = 0;

## show image
image (binEdges, 1:max(N), img)
set (gca, "ydir", "normal");
xlabel('HSV hue (in degrees)');
ylabel('Bin counts');

## print it for stackoverflow
print ("out.png")

output generated by script

Same as above but with bin width 1 (Elapsed time is 0.167423 seconds.)

binEdges = 1:360;

bin width 1

Andy
  • 7,931
  • 4
  • 25
  • 45
  • ah, and there is a little bug, the max peak is missing due to one-off... – Andy Apr 25 '17 at 18:41
  • @Rick T: Have you done some benchmarks which answer is the faster one? Because "speed" was the actual goal in your question. – Andy Apr 30 '17 at 09:12