pixelogik / ColorCube

Dominant color extraction for iOS, macOS and Python

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ColorCube returns unexpected color

dxclancy opened this issue · comments

Give the provided image, I would expect a return of a "bluish" color.

But the first color returned is the dark gray on the side, #7b7573

Is this a bug, or is this the correct return and I am misunderstanding the intent of the algorithm? It definitely seems the case that most images with this little bit of dark gray will end up choosing it. I am aware of the avoidColor/avoidDim, etc... alternatives, but i'm wondering if those "workarounds" should be necessary.

Thanks! and thanks for your code!

code:

    UIImage* image = [UIImage imageNamed:@"badDominantColor2.png"];
    CCColorCube* colorCube = [[CCColorCube alloc] init];
    NSArray* imgColors = [colorCube extractColorsFromImage:image flags:0];
    UIColor* dominantColor = imgColors[0];
    NSLog(@"color:%@", dominantColor.hexString);  // use your favorite hexString category

image:
baddominantcolor2

commented

Hi there, thanks for the report. Will check that out asap.

Does this report for you?

commented

No chance yet to check it, sorry. I guess the following is happening:

The histogram has by default 30x30x30 cells in color space, defined by

// The cell resolution in each color dimension
#define COLOR_CUBE_RESOLUTION 30

This means, that in each color dimension, there are 30 discrete steps, 27000 cells in total. In this image you have 10 pixels with the same gray color on the left, so a gray-ish cell in the histogram gets a hit count / frequency of 10. All the other pixels will be projected in different cells in the blue area of the histogram and it seems they are so wide spread that no "blue" cell becomes a frequency over 10. So the gray histogram cell wins. Also, that one gray cell will be a local maximum (disctinct). So the behaviour is correct.

In this case it would make sense to lower the resolution of the rgb histogram in order to average more over color areas, so that in this case one of the more blue-ish cells wins.

Try with values of 5 and 10 for COLOR_CUBE_RESOLUTION. This might also speed up the algorithm a little bit.

Please let me know how that works out.

Changing to 5 did give me a result I expected. It also "fixed" another instance of this "problem". (Although 10 did not for either) Of course, naturally, it also changed the extracted color result of other images that were working fine. The new colors still seem visually close to the old values to me, but I'm a little nervous about causing a change for all other images as well, since I don't understand this topic too well.

It is reasonable to say that in general the effect of changing from 30 to 5 would be that the distance between individual colors must be greater in order for them to be considered distinct? That for someone who wants very fine distinction between dominant colors would want 30? That 5 collapses more colors in a wider to range to be "the same color".

If so, I think that's what I want anyway. I don't think I want average of the entire image (although it may be that would work), but an average of the colors that visually look like the dominant color. I am already trying to clip a portion of the image that I believe is mostly the same color from a visual perspective (although the actually rgb pixel can vary a lot, and edges/highlights/antialiasing can cause large differences.)

Thanks again!

commented

Distinction is measured using euler distance in RGB space. Let's say the algorithm finds two dominant colors (local maximas in the histogram). If the euler distance between them in the RGB space is smaller than the threshold (default is 0.2), then they are NOT distinct and the second color is dropped, if distinct filter is used. The code for this is:

double delta = sqrt(redDelta*redDelta + greenDelta*greenDelta + blueDelta*blueDelta);

        // If too close mark as non-distinct and break inner loop
        if (delta < threshold) {
            isDistinct = NO;
            break;
        }

This is independent on the COLOR_CUBE_RESOLUTION however! This histogram resolution controls how much averaging of the colors is happening. The lower the resolution, the more colors are mapped to the same cell in the RGB histogram.

So if you have a histogram resolution of 5, and keep the default DISTINCT_COLOR_THRESHOLD of 0.2, the distinct filter will work the same way!

If a resolution of 5 however fits your application needs, I dont know. Best way to tell is to look at a couple of results.