Ask Your Question

Revision history [back]

The code below splits the channels and applies the transformation as documented by wikipedia. It also outputs the in between channels.

#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main(int argc, char* argv[])
{
    // OpenCV reads its channels as BGR, not as RGB!
    // You need to be aware of this in order to get the correct output
    Mat original = imread("/data/test/face.jpg");
    imshow("original", original);

    // Lets split the channels
    // index 0 = Blue / index 1 = Green / index 2 = Red
    vector<Mat> channels;
    split(original, channels);

    // Now perform the conversion from BGR to bgr - which is the chroma normalized image
    // First create empty containers for the end result
    Mat b = Mat::zeros(original.rows, original.cols, CV_32FC1);
    Mat g = b.clone(); Mat r = b.clone();
    // Grab the single channels through a meaningfull pointer
    Mat B = channels[0];
    Mat G = channels[1];
    Mat R = channels[2];
    for(int row=0; row < original.rows; row++){
        for(int col=0; col < original.cols; col++){
            b.at<float>(row,col) = (float)B.at<uchar>(row,col) / ((float)B.at<uchar>(row,col) + (float)G.at<uchar>(row,col) + (float)R.at<uchar>(row,col));
            g.at<float>(row,col) = (float)G.at<uchar>(row,col) / ((float)B.at<uchar>(row,col) + (float)G.at<uchar>(row,col) + (float)R.at<uchar>(row,col));
            r.at<float>(row,col) = (float)R.at<uchar>(row,col) / ((float)B.at<uchar>(row,col) + (float)G.at<uchar>(row,col) + (float)R.at<uchar>(row,col));
        }
    }

    // Visualise the seperate BGR channels and the combined bgr channels
    Mat combined_BGR = Mat(original.rows, original.cols*3, CV_8UC1);
    Mat combined_bgr = Mat(original.rows, original.cols*3, CV_32FC1);
    B.copyTo(combined_BGR(Rect(0,0,original.cols, original.rows)));
    G.copyTo(combined_BGR(Rect(original.cols,0,original.cols, original.rows)));
    R.copyTo(combined_BGR(Rect(original.cols*2,0,original.cols, original.rows)));
    b.copyTo(combined_bgr(Rect(0,0,original.cols, original.rows)));
    g.copyTo(combined_bgr(Rect(original.cols,0,original.cols, original.rows)));
    r.copyTo(combined_bgr(Rect(original.cols*2,0,original.cols, original.rows)));
    imshow("original channels", combined_BGR);
    imshow("rg chromacity channels", combined_bgr);

    // Combine them together
    Mat bgr = Mat(original.rows, original.cols, CV_32FC3);
    Mat in[] = { b, g, r };
    int from_to[] = { 0,0, 1,1, 2,2 };
    mixChannels( in, 3, &bgr, 1, from_to, 3 );

    // Show the result
    imshow("rg chromacity", bgr);

    waitKey(0);
}

But still the question for me is what you are trying to achieve. For visualisation purposes this data representation is pretty useless.