Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

opencv

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

like image 964
tisch Avatar asked Sep 18 '11 11:09

tisch


3 Answers

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.

like image 102
StaringFrog Avatar answered Nov 17 '22 04:11

StaringFrog


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

like image 31
Christian Avatar answered Nov 17 '22 03:11

Christian


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.

like image 1
Amir Zadeh Avatar answered Nov 17 '22 05:11

Amir Zadeh