Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a formula to determine overall color given BGR values? (OpenCV and C++)

I am making a function using C++ and OpenCV that will detect the color of a pixel in an image, determine what color range it is in, and replace it with a generic color. For example, green could range from dark green to light green, the program would determine that its still green and replace it with a simple green, making the output image very simple looking. everything is set up but I'm having trouble defining the characteristics of each range and was curious if anyone knows or a formula that, given BGR values, could determine the overall color of a pixel. If not I'll have to do much experimentation and make it myself, but if something already exists that'd save time. I've done plenty of research and haven't found anything so far.

like image 542
Wyndrix Avatar asked Jan 12 '16 01:01

Wyndrix


People also ask

What is the BGR color model?

The RGB color model is an additive color model in which the red, green, and blue primary colors of light are added together in various ways to reproduce a broad array of colors. The name of the model comes from the initials of the three additive primary colors, red, green, and blue.

What is BGR color space?

The BGR is a 24-bit representation where the lower-addressed 8 bits are blue, the next-addressed 8 are green and higher-addressed 8 are red. RGB values tend to be written as RGB(r,g,b) where the r/g/b values are between 0 and 255 inclusive or as #rrggbb, where rr/gg/bb are 8-bit hex values.

What color space does OpenCV use?

BGR color space: OpenCV's default color space is RGB. However, it actually stores color in the BGR format. It is an additive color model where the different intensities of Blue, Green and Red give different shades of color.


2 Answers

If you want to make your image simpler (i.e. with less colors), but good looking, you have a few options:

  • A simple approach would be to divide (integer division) by a factor N the image, and then multiply by a factor N.

  • Or you can divide your image into K colors, using some clustering algorithm such as kmeans showed here, or median-cut algorithm.

Original image:

enter image description here

Reduced colors (quantized, N = 64):

enter image description here

Reduced colors (clustered, K = 8):

enter image description here

Code Quantization:

#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

int main()
{
    Mat3b img = imread("path_to_image");

    imshow("Original", img);

    uchar N = 64;
    img  /= N;
    img  *= N;

    imshow("Reduced", img);
    waitKey();

    return 0;
}

Code kmeans:

#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

int main()
{
    Mat3b img = imread("path_to_image");

    imshow("Original", img);

    // Cluster

    int K = 8;
    int n = img.rows * img.cols;
    Mat data = img.reshape(1, n);
    data.convertTo(data, CV_32F);

    vector<int> labels;
    Mat1f colors;
    kmeans(data, K, labels, cv::TermCriteria(), 1, cv::KMEANS_PP_CENTERS, colors);

    for (int i = 0; i < n; ++i)
    {
        data.at<float>(i, 0) = colors(labels[i], 0);
        data.at<float>(i, 1) = colors(labels[i], 1);
        data.at<float>(i, 2) = colors(labels[i], 2);
    }

    Mat reduced = data.reshape(3, img.rows);
    reduced.convertTo(reduced, CV_8U);


    imshow("Reduced", reduced);
    waitKey();

    return 0;
}
like image 165
Miki Avatar answered Sep 20 '22 20:09

Miki


Yes, what you probably mean by "Overall color of a pixel" is either the "Hue" or "Saturation" of the color.

So you want a formula that transform RGB to HSV (Hue, Saturation, Value), and then you would only be interested by the Hue or Saturation values.

See: Algorithm to convert RGB to HSV and HSV to RGB in range 0-255 for both

EDIT: You might need to max out the saturation, and then convert it back to RGB, and inspect which value is the highest (for instance (255,0,0), or (255,0,255), etc.

like image 25
Vincent Avatar answered Sep 18 '22 20:09

Vincent