Ask Your Question
1

Convert rgb (brg) to rg chromaticity

asked 2015-02-08 18:06:26 -0600

updated 2015-08-24 17:25:19 -0600

I simply can't for the love of god do a simple damn conversion and it's been bugging me over the last weekend: https://en.wikipedia.org/wiki/Rg_chro...

Can anyone help out with an efficient way to do this in OpenCV? I keep getting black images, here's my current attempt:

for (int i = 0; i < mRgb.cols; i++) {
        for (int j = 0; j < mRgb.rows; j++) {

            Vec3b intensity = mRgb.at<Vec3b>(j, i);
            float b = intensity.val[0];
            float g = intensity.val[1];
            float r = intensity.val[2]; 

            float rgbSum = (float) (r + g + b);
            float redNorm = (float) (r / rgbSum);
            float greenNorm = (float) (g / rgbSum);
            float blueNorm = (float) (b / rgbSum); 

            res.at<Vec3b>(j, i)[0] = blueNorm;
            res.at<Vec3b>(j, i)[1] = greenNorm;
            res.at<Vec3b>(j, i)[2] = redNorm;
        }
    }

I am positive this can be done more efficiently, please help me out.

Isn't there a way in which you can split the channels, divide them to the channel sum and then add up the 3 new channels into a new image? In matlab it's done like this: http://stackoverflow.com/questions/21...

Edit, here's a second attempt using channels:

    Mat channel[3];
    split(mRgb, channel);

    double alpha = 1.0;
    double beta = 1.0;
    Mat tmpSum;
    Mat rgbSum;
    addWeighted(channel[0], alpha, channel[1], beta, 0.0, tmpSum);
    addWeighted(tmpSum, alpha, channel[2], beta, 0.0, rgbSum);

    Mat newR;
    Mat newG;
    Mat newB;
    divide(channel[0], rgbSum, newB);
    divide(channel[1], rgbSum, newG);
    divide(channel[2], rgbSum, newR);

    Mat in[] = { newB, newG, newR };
    int from_to[] = { 0, 0, 1, 1, 2, 2 };
    mixChannels(in, 3, &mRgb, 1, from_to, 3);

I get the famous fatal signal 11 on Android using OpenCV in ndk.

Regards!

edit retag flag offensive close merge delete

Comments

Well reading a bit on your own wikipedia page, it seems that: The sum of rgb will always equal one, because of this property the b dimension can be thrown away without causing any loss in information. If you think about this than getting a black image is completely normal if you visualise all 3 channels together! The idea is to do data reduction and convert your 3 channel BGR image into a 2 channel GR image. I will post some code soon!

StevenPuttemans gravatar imageStevenPuttemans ( 2015-02-11 02:22:30 -0600 )edit

2 answers

Sort by ยป oldest newest most voted
1

answered 2015-02-09 01:25:45 -0600

jamesnzt gravatar image

Try this code

#include <opencv2\opencv.hpp>
#include<iostream>

using namespace cv;
using namespace std;




int main (int argc, char** argv)
{


Mat img=imread("E:\\123.jpg",CV_LOAD_IMAGE_COLOR);


Mat A(img.size(),img.type());

if(!img.data)
{
cout<<"could not open or find the image"<<endl;
return -1;
}


namedWindow("Original",0);
imshow("Original",img);



for (int i=0;i<img.rows;i++)
{
for(int j=0;j<img.cols;j++)
{
Vec3f intensity = img.at<Vec3b>(i,j);
float blue=intensity.val[0];
float green=intensity.val[1];
float red=intensity.val[2];

double sum=red+blue+green;
double r= red/sum;
double g= green/sum;
double b = blue/sum;


       A.data[A.step[0]*i + A.step[1]* j + 0] = (b*255);
           A.data[A.step[0]*i + A.step[1]* j + 1] = (g*255);
           A.data[A.step[0]*i + A.step[1]* j + 2] = (r*255); 

    }
}

namedWindow("chrom",0);

imshow("chrom",A);


waitKey(0);

}

image description

image description

edit flag offensive delete link more

Comments

Yep, I need to normalize the new values, thanks! Any chance to adapt this to make it work as my 2nd version? Operating directly on channels?

razvan gravatar imagerazvan ( 2015-02-09 09:17:48 -0600 )edit

Please keep your answers combined :) It is not a new approach! :)

StevenPuttemans gravatar imageStevenPuttemans ( 2015-02-11 02:11:20 -0600 )edit
0

answered 2015-02-11 03:10:48 -0600

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.

edit flag offensive delete link more

Comments

mr.Razvan wanted to calculate chromaticity of the given image. He tried some program and he wants to visualize the output. he got only black screen in his attempt. the problem is according to the formula the value in the matrix is between 0 and 1 in decimals. i just multiplies the r,g,b, values with 255 to visualize the chromaticity values as image.

jamesnzt gravatar imagejamesnzt ( 2015-02-11 03:46:05 -0600 )edit

So basically it is just a scaling problem that he has?

StevenPuttemans gravatar imageStevenPuttemans ( 2015-02-11 03:58:41 -0600 )edit

yes. he also wants his second attempt to work.

jamesnzt gravatar imagejamesnzt ( 2015-02-11 04:07:34 -0600 )edit
1

In the end the scope is to try to make a better segmentation and remove shadows from the road surface. I wanted to explore the option of rg-chromaticity. Thank you very much for the answer, I will try it the next days!

razvan gravatar imagerazvan ( 2015-02-12 14:34:10 -0600 )edit

Question Tools

2 followers

Stats

Asked: 2015-02-08 18:06:26 -0600

Seen: 5,301 times

Last updated: Feb 11 '15