1 | initial version |
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.