Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I find the average of N colors?

I'm looking for a way to find the average of an unspecified number of colors. I spent a lot of time looking for a way to do this. First I tried converting my colors to CMYK and averaging them, but that didn't provide the result I expected. Then I saw that in several different places, converting the colors to CIE L*a*b* space and then averaging is the preferred way of doing this. So I looked up how to convert RGB colors to LAB space and converted into Javascript the necessary algorithms to make this happen.

Now that I have my colors in LAB space, I thought it would be as simple as finding the average of my colors, so I wrote this function to do the trick:

color.mixRGB = function() {
    var cols = Array.prototype.slice.call(arguments),
        i = cols.length,
        lab = {l: 0, a: 0, b: 0};

    while(i--) {
        if (typeof cols[i].r === "undefined" && typeof cols[i].g === "undefined" && typeof cols[i] === "undefined") {
            console.log("Not enough parameters supplied for color " + i + ".");
            return;
        }

        if(cols[i].r === 0 && cols[i].g === 0 && cols[i].b === 0) {
            cols.splice(i, 1);
        } else {
            cols[i] = color.RGBtoLAB(cols[i]);
            lab.l += cols[i].l;
            lab.a += cols[i].a;
            lab.b += cols[i].b;            
        }
    }

    lab.l /= cols.length;
    lab.a /= cols.length;
    lab.b /= cols.length;

    return color.LABtoRGB(lab);
};

If I enter RGB (255, 0, 0) and RGB(0, 0, 255) into the function, I get RGB(202, -59, 136). This color is nothing near what Color Hexa says is the average of those two RGBs, which is RGB (128, 0, 128), a.k.a purple.

I went back over all my code, and so far I've managed to determine that the problem does not lie with any of my conversion algorithms by double- and triple-checking them against Color Hexa and EasyRGB. That means either a) the issue must lie with how I'm averaging the colors or b) I've been misinformed and I shouldn't attempt to mix colors in CIE L*a*b* space.

What exactly am I missing here? Using my current algorithm, why is averaging RGB (255, 0, 0) and RGB (0, 0, 255) not giving me the same results that Color Hexa (or even visual estimation) provides? (here's a fiddle of my problem)

like image 244
Elliot Bonneville Avatar asked Jul 06 '13 21:07

Elliot Bonneville


People also ask

How do you calculate average hue?

How is average hue computed and reported? The average hue is calculated using mean of circular quantities. The standard way of computing the average cannot be used because hue is a periodic quantity (modulo 360). The ˉhr is then converted to degress using 180πˉhr(mod360).

How do I average only colored cells in Excel?

1. Select the data range and click Kutools Plus > Count by Color. You also can click Generate report to create a new workbook to list the calculate result. With Count by Color utility, you can count or sum cells by standard formatting color or conditional formatting color.

How do you find the average color in Photoshop?

Filter > Blur > Average finds the average of all of the colors in an image (or in a selection) and fills the entire image (or selection) with that color.


2 Answers

Lets say you have your colors defined by R0, G0, B0 and R1, G1, B1. Then blended/average color will have following RGB values:

RA = (R0+R1)/2;
GA = (G0+G1)/2;
BA = (B0+B1)/2;

Thats it, basically.

like image 99
David Jashi Avatar answered Oct 10 '22 05:10

David Jashi


A null return means there has been an error.

color.mixRGB = function() {
   var cols = Array.prototype.slice.call(arguments),
       i = cols.length,
       rTotal = 0, gTotal = 0, rTotal = 0, colTotal = 0;

   while(i--) {
       // NOTE: you had && in your code, I think they should be ||
       if (typeof cols[i].r === "undefined" || typeof cols[i].g === "undefined" || typeof cols[i] === "undefined") {
            console.log("Not enough parameters supplied for color " + i + ".");
            return null;
        }
        colTotal++;
        rTotal += cols[i].r;
        gTotal += cols[i].g;
        bTotal += cols[i].b;
    }
    if(colTotal === 0) return null;

    // I am not sure what you are trying to return, just build it up with your rgb values
    return (new color(Math.round(rTotal / colTotal), Math.round(gTotal / colTotal), Math.round(bTotal / colTotal)));
};
like image 35
Rewind Avatar answered Oct 10 '22 06:10

Rewind