【问题标题】:Pixel values differ between opencv and matlabopencv和matlab之间的像素值不同
【发布时间】:2015-06-30 19:57:12
【问题描述】:

当我在 matlab 中使用“显示”函数显示图像(转换为灰度的 RGB 图像)的像素值时,我发现像素值小于 1(所有值都在 0 和 1 之间)。而当我在 opencv 中做同样的事情时,我得到了更高的价值。为什么会发生价值观的变化? 打开CV代码和matlab代码如下:

for (int i = 0; i < img1.rows; i++)
{
    for (int j = 0; j < img1.cols; j++)
    {
        cout << (unsigned int)img1.at<uchar>(i, j) << endl;
    }
}

Matlab code:

gI=rgb2gray(I);
imshow(gI);

【问题讨论】:

  • 图像的数据类型是什么? doubleuint8,一些特殊的图像类? you 如何在 MATLAB 和 OpenCV 之间进行转换?我的猜测是,在 MATLAB 中,您正在处理标准化的 double 值 (0-1),而在 OpenCV 中,它们是 uint8 (0-255) 或类似的值。如果确实如此,你可以找到数据类型的最大值,并在两个系统之间进行转换。
  • matlab 是否使用了 mat2gray 函数?在stackoverflow.com/questions/27483013/scaling-a-matrix-in-opencv中尝试我的答案
  • 也许可以在 matlab 和 opencv 中发布您的示例代码
  • 我的垫子是 8UC3 类型的。如何将 MATLAB 的标准化双精度值转换为 8UC3?仅乘以 255 就足够了?

标签: matlab opencv image-processing pixel


【解决方案1】:

很抱歉让您失望了。 没有人保证将 RGB 转换为灰度会产生相同的结果。有两个原因

  1. 转换不是数学上的正确公式,而是主观问题。在过去 50 年的过程中,编写了一些不同的标准(主要用于支持灰度信号的彩色电视),以说明如何将 RGB 转换为灰度级。不同的标准导致几乎相同的可见结果,尽管像素的实际值略有不同(约 0.2%)。您可以在 Wikipedia 中阅读有关标准的更多信息。例如:一种标准定义了RGB到灰度的转换,另一种定义了RGB到YUV的转换,并以Y通道为灰度。其他标准也很少(保持亮度、强度、对比度等)。由于标准的偏好随时间而变化,因此很难知道 RGB 到灰色的具体实现方式。 Here 是 3 种不同方法的示例。 Open CV 使用完全不同的方法(0.299f*RED + 0.587f*GREEN + 0.114f*BLUEHere),而 Matlab 使用另一种方法(0.2989*RED + 0.587*GREEN + 0.1140*BLUE.Here)。注意 openCV 0.299 和 Matlabs 0.2989 之间的区别。 更多信息可以在这个答案中找到 (here)
  2. 第二个原因 - 硬件和软件之间的浮点表示不同。浮点计算(无论是双精度还是浮点)并不精确,并且取决于您使用的特定硬件、编译器类型以及您构建软件和特定编译器指令。相同的数学计算在不同的计算机上甚至在同一台计算机上的两个不同程序中可能会产生略微不同的结果。所以不幸的是,对于 RGB 到灰色的转换,您不会得到完全相同的结果,但是如果您将值四舍五入到 [0..255] 的范围内,您通常会得到不超过 2 个级别的差异。我想说的是,在 99.9% 像素中,您将获得相同的值,而在其他像素中,差异为 1。2 非常罕见,我从未见过差异为 3,除非您进行很少的顺序转换,例如 RGB->XYZ->HSV ->YUV

【讨论】:

  • 感谢您的回复。那真的很翔实。还有一个疑问。如何将 MATLAB 的标准化双精度值转换为 8UC3?仅乘以 255 就足够了?
  • 这里没有确切的答案。您可以乘以 255 并四舍五入。这会产生一个非常轻微的错误。另一种方法是乘以 256,取底(而不是四舍五入)并每隔 256 到 255 进行一次校正。这是一种较慢的算法,但可以提供更准确的结果。在转换为整数值之前,您可能希望将对比度拉伸到 1。在这种情况下,计算图像中所有像素中的最小值并将其从整个图像中减去。然后计算最大值并除以它。因此,您强制范围为 [0..1]。现在您可以应用上述技术之一
  • 通常,对比度拉伸、乘以 255 并采用 round() 被认为是默认方法。如果您确定双精度值已正确归一化 [0..1],则可以跳过对比度拉伸步骤。
【解决方案2】:

我的垫子是 8UC3 类型的。如何转换标准化的双精度值 MATLAB 到 8UC3 ?仅乘以 255 就够了吗?


8UC3 字节的情况下,yes 足以乘以 255。它们旨在以这种方式工作。 8UC中的33表示RedGreenBlue三个通道

无论如何,在0 to 255 范围值和0.0 to 1.0 范围值之间进行转换

//Psuedo-code formula:

col_val = 210; //range 0-255
normalised = col_val / 255; //always divide by 255 for a normalised to "1.0" version

normal_reverse_to255 = normalised * 255; //make it back into "0 to 255" range

预期结果:
col_val = 210 //original value before normalised
标准化 = 0.8235 //...294117647058 etc etc //after normalised to 0.0 to 1.0 range
normal_reverse_to255 = 210; //multiply result is same as original value

希望对你有帮助。

编辑:
我刚刚意识到您正在使用gI=rgb2gray(I); 来获取您的灰度图像。

尝试类似:
cvtColor(src,dst,CV_GRAY2RGB);this answer 劫持

【讨论】:

    猜你喜欢
    • 2020-01-13
    • 1970-01-01
    • 2015-08-02
    • 2015-10-14
    • 2017-02-24
    • 2019-02-24
    • 2013-07-25
    • 1970-01-01
    相关资源
    最近更新 更多