Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Convert Luminous and Color Opponent Channels to RGB Image

I converted the RGB channels of an image to luminous and color opponent channels; now I am trying to convert the opponent channels back to RGB (using only luminous and the opponent channels), but I do not know how to compute R, G, and B given luminous, red-green, and yellow-blue. How do we go back to RGB from luminuous, red-green, and yellow-blue?

My Method

I converted the RGB image to the opponent channels using the method here: https://github.com/opencv/opencv/blob/2.4/modules/features2d/src/descriptors.cpp#L126. I am not sure why this method does green-red for the red-green channel; for the moment I changed that part to do red-green instead.

To get the original image back, i converted each channel to RGB. For luminous:

cv::Vec3b& pixel = rgbEquivalent->at<cv::Vec3b>(y, x);
pixel[0] = pixel[1] = pixel[2] = channel.at<uchar>(y, x);

For red-green and yellow-blue (I expect this is where the problem is):

float opponency = (float)channel.at<uchar>(y, x);

//Depending on the opponent channel, may represent red or yellow.
float redOrYellow = (opponency - 128.0f) * 2.0f;
//Depending on the opponent channel, may represent green or blue.
float greenOrBlue = (128.0f - opponency) * 2.0f;

if (redOrYellow < 0.0f)
    redOrYellow = 0.0f;

if (greenOrBlue < 0.0f)
    greenOrBlue = 0.0f;

if (type == RED_MINUS_GREEN)
{
    pixel[0] = 0;
    pixel[1] = (uchar)greenOrBlue;
    pixel[2] = (uchar)redOrYellow;
}
else
{
    pixel[0] = (uchar)greenOrBlue;
    pixel[1] = (uchar)redOrYellow;
    pixel[2] = (uchar)redOrYellow;
}

For the image:

Original image

I achieved these RGB representations of each channel

Luminous redminusgreen yellowminusblue

I then get the original back by taking the average RGB value: reconst0

But this image is too dark. Maybe the color difference channels are too dark to begin with?

Summing all the RGB values is not right either: it results in random color patches due to some values going above 255:

reconst1

Convert Luminous and Color Opponent Channels to RGB Image

I converted the RGB channels of an image to luminous and color opponent channels; now I am trying to convert the opponent channels back to RGB (using only luminous and the opponent channels), but I do not know how to compute R, G, and B given luminous, red-green, and yellow-blue. How do we go back to RGB from luminuous, red-green, and yellow-blue?

My Method

I converted the RGB image to the opponent channels using the method here: https://github.com/opencv/opencv/blob/2.4/modules/features2d/src/descriptors.cpp#L126. I am not sure why this method does green-red for the red-green channel; for the moment I changed that part to do red-green instead.

To get the original image back, i converted each channel to RGB. For luminous:

cv::Vec3b& pixel = rgbEquivalent->at<cv::Vec3b>(y, x);
pixel[0] = pixel[1] = pixel[2] = channel.at<uchar>(y, x);

For red-green and yellow-blue (I expect this is where the problem is):

float opponency = (float)channel.at<uchar>(y, x);
cv::saturate_cast<float>(channel.at<uchar>(y, x));

//Depending on the opponent channel, may represent red or yellow.
float redOrYellow = (opponency - 128.0f) * 2.0f;
//Depending on the opponent channel, may represent green or blue.
float greenOrBlue = (128.0f - opponency) * 2.0f;

if (redOrYellow < 0.0f)
    redOrYellow = 0.0f;

if (greenOrBlue < 0.0f)
    greenOrBlue = 0.0f;

if (type == RED_MINUS_GREEN)
{
    pixel[0] = 0;
    pixel[1] = (uchar)greenOrBlue;
cv::saturate_cast<uchar>(greenOrBlue);
    pixel[2] = (uchar)redOrYellow;
cv::saturate_cast<uchar>(redOrYellow);
}
else
{
    pixel[0] = (uchar)greenOrBlue;
cv::saturate_cast<uchar>(greenOrBlue);
    pixel[1] = (uchar)redOrYellow;
cv::saturate_cast<uchar>(redOrYellow);
    pixel[2] = (uchar)redOrYellow;
cv::saturate_cast<uchar>(redOrYellow);
}

For the image:

Original image

I achieved these RGB representations of each channel

Luminous redminusgreen yellowminusblueluminous redminusgreen yellowminusblue

I then get the original back by taking the average RGB value: reconst0

But this image is too dark. Maybe the color difference channels are too dark to begin with?value:

reconst1

Summing all the RGB values is not right either: it results in random color patches due to some values going above 255:

reconst1an image that seems slightly too bright (or yellow?):

reconst2

Convert Luminous and Color Opponent Channels to RGB Image

I converted the RGB channels of an image to luminous and color opponent channels; now I am trying to convert the opponent channels back to RGB (using only luminous and the opponent channels), but I do not know how to compute R, G, and B given luminous, red-green, and yellow-blue. How do we go back to RGB from luminuous, red-green, and yellow-blue?

My Method

I converted the RGB image to the opponent channels using the method here: https://github.com/opencv/opencv/blob/2.4/modules/features2d/src/descriptors.cpp#L126. I am not sure why this method does green-red for the red-green channel; for the moment I changed that part to do red-green instead.

To get the original image back, i converted each channel to RGB. For luminous:

cv::Vec3b& pixel = rgbEquivalent->at<cv::Vec3b>(y, x);
pixel[0] = pixel[1] = pixel[2] = channel.at<uchar>(y, x);

For red-green and yellow-blue (I expect this is where the problem is):

float opponency = cv::saturate_cast<float>(channel.at<uchar>(y, x));

//Depending on the opponent channel, may represent red or yellow.
float redOrYellow = (opponency - 128.0f) * 2.0f;
//Depending on the opponent channel, may represent green or blue.
float greenOrBlue = (128.0f - opponency) * 2.0f;

if (redOrYellow < 0.0f)
    redOrYellow = 0.0f;

if (greenOrBlue < 0.0f)
    greenOrBlue = 0.0f;

if (type == RED_MINUS_GREEN)
{
    pixel[0] = 0;
    pixel[1] = cv::saturate_cast<uchar>(greenOrBlue);
    pixel[2] = cv::saturate_cast<uchar>(redOrYellow);
}
else
{
    pixel[0] = cv::saturate_cast<uchar>(greenOrBlue);
    pixel[1] = cv::saturate_cast<uchar>(redOrYellow);
    pixel[2] = cv::saturate_cast<uchar>(redOrYellow);
}

For the image:

Original image

I achieved these RGB representations of each channel

luminous redminusgreen yellowminusblue

I then get the original back by taking the average RGB value:value, but it seems too dark:

reconst1

Summing all the RGB values results in an image that seems slightly too bright (or yellow?):

reconst2

Convert Luminous and Color Opponent Channels to RGB Image

Update - I changed the RGB to opponent conversion to that posted here: https://www.mathworks.com/matlabcentral/answers/118889-rgb-to-opponent-color-space-code

I converted the RGB channels of an image to luminous and color opponent channels; now I am trying to convert the opponent channels back to RGB (using only luminous and the opponent channels), but I do not know how to compute R, G, and B given luminous, red-green, and yellow-blue. How do we go back to RGB from luminuous, red-green, and yellow-blue?

My Method

I converted the RGB image to the opponent channels using the method here: https://github.com/opencv/opencv/blob/2.4/modules/features2d/src/descriptors.cpp#L126here. I am not sure why this method does green-red for the red-green channel; for the moment I changed that part to do red-green instead.The conversion goes:

//Red minus green
opponentChannels[0].at<float>(y, x) = (r - g) / std::sqrt(2.0f);

//Yellow minus blue
opponentChannels[1].at<float>(y, x) = (r + g - (2 * b)) / std::sqrt(6.0f);

//Luminous
opponentChannels[2].at<float>(y, x) = (r + g + b) / std::sqrt(3.0);

where r, g, and b are floats and x and y are the coodinates of the pixel being set.

To get the original image back, i converted each channel to RGB. For luminous:

cv::Vec3b& cv::Vec3f& pixel = rgbEquivalent->at<cv::Vec3b>(y, rgbEquivalent->at<cv::Vec3f>(y, x);
//Multiply by sqrt(3.0f) / 3.0f to put in the range of [0.0,1.0].
pixel[0] = pixel[1] = pixel[2] = channel.at<uchar>(y, x);
luminous.at<float>(y, x) * (std::sqrt(3.0f) / 3.0f);

For red-green and yellow-blue (I expect this is where the problem is):

float opponency = cv::saturate_cast<float>(channel.at<uchar>(y, x));

//Depending on the opponent channel, may represent red or yellow.
float redOrYellow = (opponency - 128.0f) * 2.0f;
//Depending on the opponent channel, may represent green or blue.
float greenOrBlue = (128.0f - opponency) * 2.0f;

if (redOrYellow < 0.0f)
    redOrYellow = 0.0f;

if (greenOrBlue < 0.0f)
    greenOrBlue = 0.0f;

if (type == RED_MINUS_GREEN)
{
    //Multiply by sqrt(2.0f) to put in the range [0.0, 1.0]
    float red = color * std::sqrt(2.0f);
    float green = -red;

    if (red < 0.0f)
        red = 0.0f;

    if (green < 0.0f)
        green = 0.0f;

    pixel[0] = 0;
0.0;
    pixel[1] = cv::saturate_cast<uchar>(greenOrBlue);
green;
    pixel[2] = cv::saturate_cast<uchar>(redOrYellow);
red;
}
else
else if (type == YELLOW_MINUS_BLUE)
{
    //Multiply by sqrt(6.0f) / 2.0f to put in the range of [0.0, 1.0]
    float yellow = color * (std::sqrt(6.0f) / 2.0f);
    float blue = -yellow;

    if (yellow < 0.0f)
        yellow = 0.0f;

    if (blue < 0.0f)
        blue = 0.0f;

    pixel[0] = cv::saturate_cast<uchar>(greenOrBlue);
blue;
    pixel[1] = cv::saturate_cast<uchar>(redOrYellow);
yellow;
    pixel[2] = cv::saturate_cast<uchar>(redOrYellow);
yellow;
}

For the image:

Original image

I achieved these RGB representations of each channel

luminous redminusgreen yellowminusblue

I then get the original back by taking the average RGB value, but it seems too dark:

reconst1

Summing all the RGB values results in an image that seems slightly too bright (or yellow?):

reconst2