tisch
tisch

Reputation: 1118

OpenCV image conversion from RGB to Grayscale using imread giving poor results

I'm loading a 24 Bit RGB image from a PNG file into my OpenCV application.

However loading the image as grayscale directly using imread gives a very poor result.

Mat src1 = imread(inputImageFilename1.c_str(), 0);

Loading the RGB image as RGB and converting it to Grayscale gives a much better looking result.

Mat src1 = imread(inputImageFilename1.c_str(), 1);
cvtColor(src1, src1Gray, CV_RGB2GRAY);

I'm wondering if I'm using imread for my image type correctly. Has anyone experienced similar behavior?

The image converted to grayscale using imread is shown here: Bad result

The image converted to grayscale using cvtColor is shown here: Good result

Upvotes: 17

Views: 68063

Answers (3)

Christian
Christian

Reputation: 134

The simple answer is, that openCV functions uses the BGR format. If you read in a image with imread or VideoCapture, it'll be always BGR. If you use RGB2GRAY, you interchange the blue channel with the green. The formula to get the brightness is

y = 0.587*green + 0.299*red + 0.114*blue

so if you change green and blue, this will cause an huge calculation error.

Greets

Upvotes: 10

StaringFrog
StaringFrog

Reputation: 561

I was having the same issue today. Ultimately, I compared three methods:

//method 1
cv::Mat gs = cv::imread(filename, CV_LOAD_IMAGE_GRAYSCALE);

//method 2
cv::Mat color = cv::imread(filename, 1); //loads color if it is available
cv::Mat gs_rgb(color.size(), CV_8UC1);
cv::cvtColor(color, gs_rgb, CV_RGB2GRAY);

//method 3
cv::Mat gs_bgr(color.size(), CV_8UC1);
cv::cvtColor(color, gs_bgr, CV_BGR2GRAY);

Methods 1 (loading grayscale) and 3 (CV_BGR2GRAY) produce identical results, while method 2 produces a different result. For my own ends, I've started using CV_BGR2GRAY.

My input files are jpgs, so there might be issues related to your particular image format.

Upvotes: 20

Amir Zadeh
Amir Zadeh

Reputation: 3629

I have had a similar problem once, working with OpenGL shaders. It seems that the first container that OpenCV reads your image with does not support all the ranges of color and hence you see that the image is a poor grayscale transformation. However once you convert the original image into grayscale using cvtColor the container is different from the first one and supports all ranges. In my opinion the first one uses less than 8 bits for grayscale or changing to the grayscale uses a bad method. But the second one gives smooth image because of more bits in gray channel.

Upvotes: 1

Related Questions