# What Measure to Compare the Color Depth (Distribution of Colors) of Images

I am looking to compare the color depth of multiple images, in order to see which one has the best color depth. I was wondering what is the best way to compute color depth computationally?

I've seen something called bit depth used to measure color depth, however that doesn't seem totally right...

Like between these 2 images,

The second image has better color depth, but from the image details I saw both of the bit depth are 24. So is there a way to measure color depth or measure of the color space which then would in a way show that the second image's color depth is better than the first?

One measure you may use is the Entropy (Information Theory) of the data.
Its definition is given by:

$$H \left( X \right) := - \sum_{x \in \mathcal{X}} p \left( x \right) \log p \left( x \right) = \mathbb{E} \left[- \log p \left( X \right) \right]$$

So we need to deal with 2 things:

1. Calculate the histogram of the image.
2. Deal with the multiple channels.

A simple way would be calculating the entropy on each channel (RGB) then average the result. Yet this won't take into account the actual color space.

One could even use different color space, like calculating the entropy of the luminance or the hue channels in HSL model.

One way to treat each pixel as a vector in space would be converting the image into 8 Bit / Channel space and then create an histogram for 24 Bit numbers (Usually using UINT32 / INT32). Then calculate the entropy on this histogram.

### MATLAB Code

The function to calculate the entropy is given by:

function [ imgEntropy ] = CalcImgEntropy( mI, entropyMode )

FALSE   = 0;
TRUE    = 1;

OFF     = 0;
ON      = 1;

ENTROPY_MODE_CHANNEL    = 1; %<! Averages per channel calculation
ENTROPY_VECTOR          = 2; %<! Treats the RGB data as a single vector per pixel

numRows     = size(mI, 1);
numCols     = size(mI, 2);
numChannels = size(mI, 3);

if(numChannels > 8)
% 8 channels of uint8 can be packed into uint64
error('Input Image Must Have # Channels < 8');
end

if(numChannels == 1)
imgEntropy = CalcEntropy(mI);
else
if(entropyMode == ENTROPY_MODE_CHANNEL)
imgEntropy = 0;
for ii = 1:numChannels
imgEntropy = imgEntropy + CalcEntropy(mI(:, :, ii));
end
imgEntropy = imgEntropy / numChannels;
elseif(entropyMode == ENTROPY_VECTOR)
if(numChannels > 4)
mI = uint64(mI);
else
mI = uint32(mI);
end
mD = mI(:, :, 1);
for ii = 2:numChannels
mD = mD + bitshift(mI(:, :, ii), 8 * (ii - 1));
end
imgEntropy = CalcEntropy(mD(:));
end
end

end

function [ valEntropy ] = CalcEntropy( vI )

vU = unique(vI(:));
vP = histc(vI(:), vU);

vP = vP / sum(vP); %<! Make it probability

valEntropy = -sum(vP .* log2(vP));

end



As one can see, for the "vector" case the function packs each 8 but channel into a longer representation. Then it calculates the entropy.

The results I get:

Where Image 001 is given by:

Image 002 is given by:

Indeed the entropy of the 2nd image is higher which means it has more colors and its histogram is more uniform.

The full code is available on my StackExchange Signal Processing Q84826 GitHub Repository (Look at the SignalProcessing\Q84826 folder).

### Update

I also added a Julia code to implement the above (Same location).

Since both images are stored using a format with the same bit depth then, I believe that you want to know the total amount of colors used.

Using pseudo-code, it would be something like

my_image = array(x,y)
colors = array(bit depth)

for m = 0 to x
for n = 0 to y
int rgb = red[m,n]
rgb = (rgb << 8) + green[m,n]
rgb = (rgb << 8) + blue[m,n]
colors[rgb]+=1


to provide an individual color count. Then you can compare both images, for example, or just sum up everything.

You might also be interested in color contrast, which is calculated based on the luminance channel.

It is not clear what you want, but from those two images it seems to me that what you want to measure is color saturation.

From an sRGB representation you probably can do a decent score based on the deviation of [r,g,b] from their (possibly weighted) mean.

You got apparently working answer, but let me provide another view. Instead of working in RGB you can study the image in HSV color model. In HSV "S" stands for saturation and it seems you are interested in that.

In octave we can load the image in HSV and study the mean

>> firstIM = imread("C95vE.jpg");