dominant color for an RGB image

32 ビュー (過去 30 日間)
mariem farhat
mariem farhat 2013 年 2 月 26 日
回答済み: DGM 2022 年 5 月 10 日
Hello,
I want to extract the dominant color of an RGB image.
How can I proceed to do that?
  23 件のコメント
Shiv srikakolum
Shiv srikakolum 2021 年 11 月 24 日
Thank you so much @Image Analyst
DGM
DGM 2022 年 5 月 10 日
This line
[rMax, gMax, bMax] = ind2sub(size(rgbImage), indexes);
should be
[rMax, gMax, bMax] = ind2sub(size(rgbHist), indexes);

サインインしてコメントする。

回答 (4 件)

Sean de Wolski
Sean de Wolski 2013 年 2 月 27 日
colors = 'RGB';
I = imread('peppers.png');
[~,idx] = max(sum(sum(I,1),2),[],3);
dominant = colors(idx)

Image Analyst
Image Analyst 2013 年 2 月 26 日
How about this:
dominantRedValue = mean2(rgbImage(:, :, 1));
dominantGreenValue = mean2(rgbImage(:, :, 2));
dominantBlueValue = mean2(rgbImage(:, :, 3));
Will that work for you?
  11 件のコメント
Walter Roberson
Walter Roberson 2013 年 2 月 27 日
Darned if I can tell. Unless, that is, we start referring to Hue rather than "color"
Image Analyst
Image Analyst 2013 年 2 月 27 日
編集済み: Image Analyst 2021 年 11 月 23 日
Even looking at hue, it's not so easy, as you can see from this screenshot:
That's looking down the value axis from the top. Here's another view from a different perspective:
As you can see whether there is more "green" or "white" pixels depend on where you put the "dividing line" between green and white. It's sort of a continuum so you have to make some kind of criteria. Basically you have to do color classification but to do that you have to decide how many colors you want. Here's one where I chose 48 color classes:
but there are still classes in the "in between" greenish/whitish region and you'll have to decide what to call those. But after that you can find out how many pixels are in each class, then maybe boil it down to two classes and see which has more pixels in it.

サインインしてコメントする。


mariem farhat
mariem farhat 2013 年 2 月 27 日
Sorry, I haven't posted the image. Here the link of the image:
  5 件のコメント
Walter Roberson
Walter Roberson 2013 年 2 月 27 日
There are so many shades of green there, that I think it plausible that there might be more white than any particular shade of green.
Jan
Jan 2017 年 4 月 25 日
The imageshack link is dead now. Please post the image directly instead of hosting it on any external server.

サインインしてコメントする。


DGM
DGM 2022 年 5 月 10 日
For sake of alternatives, MIMT imstats() has a few options that might be of use here.
While imstats can obviously calculate things like mean, median, or mode, the pagewise mode is usually not what's intended.
rgbpict = imread('peppers.png');
cc = imstats(rgbpict,'mode')
cc =
255 36 0
While there's a lot of red in the image, that tuple does not exist anywhere in the image. Does that matter in your application? It's certainly not close to the most common color either.
From the synopsis:
% 'mode' returns the mode (most common values) per channel
% 'modecolor' calculates the most common color. This differs from 'mode' as
% the most frequent values in individual channels are not necessarily colocated.
% Consider an image which is 40% [1 0 0], 30% [1 1 1] and 30% [0 1 1].
% For this example, 'mode' returns [1 1 1], whereas 'modecolor' returns [1 0 0].
% The latter would be the intuitive answer.
% 'moderange' calculates a selected range of the most common colors in the image.
% Contrast this with 'modecolor' which calculates the singular most common color.
% The range of colors and number of output tuples is specified by parameter 'nmost'.
% This mode supports only I/RGB images.
% 'modefuzzy' calculates the frequency-weighted mean of a selected range of the
% most common colors in the image. The range of colors is specified by parameter
% 'nmost'. This mode supports only I/RGB images.
% The 'modecolor', 'modefuzzy', and 'moderange' options all do color quantization,
% and can therefore alter the color population to some degree. Be wary of using
% the output of these modes for anything of technical importance.
Pay attention to the caveats. The need for quantization is a compromise for speed and memory conservation. Consider how a simple 3D histogramming method might work when the input is a floating-point or uint16 image. The goal of these special 'mode' options is more about visual appearances than exactly matching any one pixel in the image.
Consider the following example. This helps illustrate the different results returned by the various options.
rgbpict = imread('peppers.png');
% get some different image stats
cc = imstats(rgbpict,'mean','median','mode','modecolor','modefuzzy','moderange','nmost',10);
% use those stats to construct a swatch chart for single-output stats
labels = {'mean','median','mode','modecolor','modefuzzy'};
sz = imsize(rgbpict,2);
ntiles = (numel(labels));
tilesz = [round(sz(1)/ntiles) 100];
block1 = zeros([tilesz 3 ntiles],'uint8');
for k = 1:ntiles
thistile = colorpict([tilesz 3],cc(k,:),'uint8'); % colored swatch
thislabel = im2uint8(textim(labels{k},'ibm-iso-16x9')); % text label image
thistile = im2uint8(imstacker({thislabel thistile},'padding',0)); % match geometry
block1(:,:,:,k) = mergedown(thistile,1,'lineardodge'); % blend label and swatch
end
block1 = imtile(block1,[ntiles 1]); % vertically arrange tiles
block1 = imresize(block1,[sz(1) tilesz(2)]); % make sure it's the right size
% create another chart for moderange's multiple outputs
ntiles = (size(cc,1)-ntiles);
tilesz = [round(sz(1)/ntiles) 100];
block2 = zeros([tilesz 3 ntiles],'uint8');
for k = 1:ntiles
thistile = colorpict([tilesz 3],cc(k+4,:),'uint8'); % colored swatch
thislabel = im2uint8(textim(num2str(k),'ibm-iso-16x9')); % text label image
thistile = im2uint8(imstacker({thislabel thistile},'padding',0)); % match geometry
block2(:,:,:,k) = mergedown(thistile,1,'lineardodge'); % blend label and swatch
end
block2 = imtile(block2,[ntiles 1]); % vertically arrange tiles
block2 = imresize(block2,[sz(1) tilesz(2)]); % make sure it's the right size
% show the combined images
imshow([rgbpict block1 block2])
As mentioned before, the results from 'mode' are obviously not the visually-dominant color. In this particular example, 'modecolor' and 'modefuzzy' return similar results. The results from 'moderange' are all very similar. This similarity is not generally the case, so in those cases, you may see 'modefuzzy' results become skewed.
Consider the same code run on other images:
Note how the most frequent colors in the lighthouse image are represented by two different objects/regions. The results from 'modefuzzy' really only make sense if those colors come from one visually distinct region/object, otherwise it won't make sense to take the weighted mean of them. Similar happens with the rubber band picture.
I'm sure that there are some sort of clustering techniques that would work for this task, but I'll leave that to someone who's familiar with it. I just figured I'd throw this out there. For simple things like color-matching components of an image composition, these imstats() options offer a convenience in simple syntax and relatively low resource cost, even if the quantization reduces their usefulness in more technical contexts. While 'modefuzzy' and 'moderange' only work on I/RGB images, most options (including 'modecolor') work on any I/IA/RGB/RGBA/RGBAAA image.

Community Treasure Hunt

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

Start Hunting!

Translated by