ofPixels and image data

Hi there,

I’m trying to extract various bits of data from images and thought it would be useful to be able to use functions like ‘getSaturation’ etc. from ofColor.

Unfortunately it seems getting average values for a whole image or sections of an image is not as easy as it looks. As a bit of a workaround, I’ve been trying to do the following:

  • loop through each pixel, adding up every value for each channel
  • divide each total by the number of pixels
  • create an ofColor using the averages for all the channels
  • use the functions on the new ofColor

However, I’m not sure I’m doing this right. This is what I have so far:

imageToLoad.loadImage("test3.jpg");

int w = imageToLoad.getWidth();
int h = imageToLoad.getHeight();

ofPixels loadedPixels = imageToLoad.getPixels();
int numChannels = loadedPixels.getNumChannels();

if(numChannels >= 3)
{
    for (int i=0; i<w*h; i++)
    {
        currentPixels = imageToLoad.getPixels()[i]
        r_totalPixelVal = r_totalPixelVal + currentPixels.getChannel(0);
        g_totalPixelVal = g_totalPixelVal + currentPixels.getChannel(1);
        b_totalPixelVal = b_totalPixelVal + currentPixels.getChannel(2);
    }
}
else
{
    for (int i=0; i<w*h; i++)
    {
        currentPixels = imageToLoad.getPixels()[i]
        gs_totalPixelVal = gs_totalPixelVal + currentPixels.getChannel(0);
    }
};

int numPixels = w*h;

r_averagePixelVal = (r_totalPixelVal / numPixels);
g_averagePixelVal = (g_totalPixelVal / numPixels);
b_averagePixelVal = (b_totalPixelVal / numPixels);

gs_averagePixelVal = (gs_totalPixelVal / numPixels);

I’m getting a “No match for Operator=” error with the line

loadedPixels = imageToLoad.getPixels();

So I’m assuming that’s not right. Can anyone help me out with this? Or is there a better way of achieving what I want?

hey @SuburbanKnight,

I do believe the compilation error that you’re getting is the result of calling ofImage::getPixels() instead of ofImage::getPixelsRef(). The former returns a pointer to the pixel array while the latter returns a ofPixels structure. For parsing a bitmap, I find it easier to use getPixels().

Here’s an example using that approach:

int w = imageToLoad.getWidth();
int h = imageToLoad.getHeight();
int numPixels = w * h;

unsigned char * loadedPixels = imageToLoad.getPixels();
int numChannels = loadedPixels.getNumChannels();

if(numChannels >= 3)
{
    for (int i=0; i<numPixels; i++)
    {
        int pix = i * numChannels;
        r_totalPixelVal += loadedPixels[pix]; // red pixels
        g_totalPixelVal += loadedPixels[pix+1]; // green pixels
        b_totalPixelVal += loadedPixels[pix+2]; // blue pixels
    }
}
else
{
    for (int i=0; i<numPixels; i++)
    {
        gs_totalPixelVal += loadedPixels[i]; // grayscale
    }
};

r_averagePixelVal = (r_totalPixelVal / numPixels);
g_averagePixelVal = (g_totalPixelVal / numPixels);
b_averagePixelVal = (b_totalPixelVal / numPixels);

gs_averagePixelVal = (gs_totalPixelVal / numPixels);

Hope that helps!

Cheers, that’s done it! (although the blue and green channels are swapped for some reason). Thanks a lot!

Weirdly though now, using functions like getHue and getBrightness give the wrong values when used on the ofColor set with the RGB values. Here’s an example using an image with just pure colour:

averageColor.set(r_averagePixelVal, g_averagePixelVal, b_averagePixelVal);
//...
cout << "Average Hue Value        = " << averageColor.getHue() << "\n";
cout << "Average Saturation Value = " << averageColor.getSaturation() << "\n";
cout << "Average Brightness Value = " << averageColor.getBrightness() << "\n";

and here’s the output:

Any idea? Is it something I’m doing wrong?

I’m not sure if your green and blue values are swapped, or just printed to the console in the wrong order.

When I punch those numbers into Photoshop’s color picker, the values are consistent with the ones that you’re printing out in OF.

You’re printing the results of averageColor.getHueAngle() in the console, correct?

In Photoshop, for RGB 95/202/148, the HSB values are get 150-degrees, 53% (132), 79% (201).

The difference in the hue value in the UI you’re comparing against could in a range of 0 to 255 (represented as a char), not 0 to 360 (represented in degrees).