2011-09-18 124 views
15

我从PNG文件加载24位RGB图像到我的OpenCV应用程序中。OpenCV图像从RGB转换为灰度使用imread给出差的结果

但是直接使用imread直接将图像加载为灰度会产生非常差的结果。

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

将RGB图像加载为RGB并将其转换为灰度可获得更好的效果。

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

我想知道我是否正确使用imread作为我的图像类型。有没有人遇到类似的行为?

的影像转换成使用imread灰度如下所示: Bad result

的影像转换成使用cvtColor灰度如下所示: Good result

+5

OpenCV中的“彩色”图像表示BGR。所以你的代码的第二个版本是不正确的。它应该使用'CV_BGR2GRAY'进行颜色转换。 –

+0

感谢您的评论。我试图使用CV_BGR2GRAY而不是CV_RGB2GRAY将图像转换为灰度,但得到了相同的结果。 – tisch

+0

你能否附上你的原始图像? –

回答

16

今天我有同样的问题。最后,我比较了三种方法:

//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); 

方法1(装载灰度)和3(CV_BGR2GRAY)产生相同的结果,而方法2产生不同的结果。为了我自己的目的,我开始使用CV_BGR2GRAY。

我的输入文件是jpgs,所以可能存在与您的特定图像格式相关的问题。

+0

Opencv imread以BGR格式返回图像,所以我认为正确转换为GRAY Scale是CV_BGR2GRAY,正如您在第三种方法中提到的 – evk1206

1

我也有过类似的问题一次,用OpenGL着色器。看来OpenCV第一个读取图像的容器并不支持所有的颜色范围,因此您会发现该图像是灰度不佳的转换。但是,一旦您使用cvtColor将原始图像转换为灰度,容器与第一个不同,并支持所有范围。在我看来,第一个使用少于8位的灰度或改变灰度使用不好的方法。但是第二个由于灰色通道中的更多位而给出了平滑的图像。

+0

您是否找到支持此推理的文档?面对一个类似的问题,我倾向于相信这可能是这种情况,但找不到任何结论性的东西在我的推理 – Ani

+0

那么情况是这样的,因为帧缓冲区包含255每种颜色的范围和255单色光谱。您需要浮点来支持更好的范围。 –

10

简单的答案是,openCV函数使用BGR格式。如果您阅读imreadVideoCapture的图片,它将始终是BGR。如果您使用RGB2GRAY,则将蓝色通道与绿色交换。获得亮度的公式是

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

所以如果你改变绿色和蓝色,这将导致巨大的计算错误。

Greets

+1

那么它是不是也在交换红色通道?在这种情况下,将给定的'BGR'解释为'RGB',然后导致(实际)'B'被错误地解释为'R',并且'R'解释为'B'? 那么根据你的回答,这个修复将会用'CV_BGR2GRAY'替换'cvtColor'调用中的'CV_RGB2GRAY'? –