Clear Filters
Clear Filters

How to calculate the percentage of each color in this image ?

40 views (last 30 days)
How to calculate the percentage of each color in this image ?
  10 Comments
Image Analyst
Image Analyst on 29 Dec 2020
If the box is dark and continuous (unbroken) enough then you can simply threshold
boxMask = grayImage < somethreshold;
Now you have to throw away everything outside the box. If everything else touches the border of the image you can do
boxMask = imclearborder(boxMask);
Then fill what's left
% Might need to take the largest blob that's left
boxMask = bwareafilt(boxMask, 1);
% Fill holes to fill in where the letters were
boxMask = imfill(boxMask, 'holes');
props = regionprops(boxMask, 'BoundingBox')
croppedImage = imcrop(rgbImage, props.BoundingBox);
Adam Danz
Adam Danz on 29 Dec 2020
Here's a complete demo showing how to compute the number of pixels per color in an image. That can easily be used to compute the percentage of each color.

Sign in to comment.

Answers (1)

DGM
DGM on 19 Jul 2024 at 14:59
Edited: DGM on 19 Jul 2024 at 20:50
I was bored and thought that the image itself was interesting.
% decoding this image will produce a warning
inpict = imread('image.png');
Warning: PNG library warning:
sBIT: invalid
% isolate the bars themselves
% i assume that the image is clean (NOT JPG)
% and that HSV saturation will adequately isolate the bars
[~,S,~] = rgb2hsv(inpict);
% threshold S
% pick the largest 5 objects (the bars)
mask = bwareafilt(S>0.5,5);
% get object geometry
P = regionprops(mask,'boundingbox');
bb = vertcat(P.BoundingBox);
% things we know from the plot:
% we know the category names
% we know that counts are non-negative integers
% we know the peak count is 11
maxcnt = 11;
% estimate counts from bar height
% i'm using height instead of area, since there's no reason to
% incorporate error from irrelevant degrees of freedom
cnt = round(bb(:,4)./max(bb(:,4))*maxcnt)
cnt = 5x1
4 8 11 6 5
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
% calculate contribution from each category
% if you want to make these numbers less useful,
% feel free to multiply them by 100.
pct = cnt./sum(cnt)
pct = 5x1
0.1176 0.2353 0.3235 0.1765 0.1471
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
The given image is a fully opaque uint8 RGB image expressed as uint8 RGBA with a solid alpha channel, and encoded in PNG with an improper 3-term RGB sBIT specification ([8 8 8]) instead of the required 4-term RGBA sBIT specification ([8 8 8 8]).
In other words, this file was written as RGBA with RGB sBIT spec, when it should have been written as either:
  • RGB with RGB sBIT spec
  • RGBA with RGBA sBIT spec
I have no idea what software created this bogus file, but the metadata just says 'Google'. Either the encoder is improperly setting this field with default values, or the user is explicitly specifying them incorrectly. The fact that they're native 8b/ch suggests that a user would have no reason to set them anyway.
Note that this given image makes several things reasonably clear. We know that these are discrete counts, so the bar heights represent non-negative integers. It's seemingly clear what the value of the tallest bar is. If that reference value were not obvious, the whole process would be more complicated.
Similarly, the process would be more complicated if saturation were not adequate for isolating the bars from other parts of the image. If the bars were drawn with a very thick border (as in the prior pie charts), the error would be increased accordingly. While integer rounding may be adequate to suppress such a problem in this specific case, we can't always rely on the represented values being small integers.
Likewise, we're assuming that the tallest bar is not actually truncated at the plot box extents. That's not always an accurate assumption.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!