Python 有多种方法可以从 RGB 版本生成灰度图像。其中之一就是使用 OpenCV 将图像读取为灰度。
im = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
有许多不同的算法来处理此操作这里有很好的解释。
我想知道 OpenCV 如何处理这个任务以及哪种算法支持
cv2.IMREAD_GRAYSCALE
,但找不到任何文档或参考。有人有什么想法吗?纸质参考文献会很棒。
提前致谢
附注我正在处理 jpg 和 png。
在 OpenCV 文档中你可以找到:
IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image (codec internal conversion).
还有
使用IMREAD_GRAYSCALE时,编解码器内部的灰度转换 如果可用的话将被使用。 结果可能与 cvtColor() 的输出不同
所以这取决于编解码器内部的灰度转换。
更多信息:来自 OpenCV 文档
使用 IMREAD_GRAYSCALE 时,将使用编解码器的内部灰度转换(如果可用)。结果可能与 cvtColor() 的输出不同 在 Microsoft Windows* 操作系统和 MacOSX* 上,默认使用 OpenCV 图像附带的编解码器(libjpeg、libpng、libtiff 和 libjasper)。因此,OpenCV 始终可以读取 JPEG、PNG 和 TIFF。在 MacOSX 上,还可以选择使用本机 MacOSX 图像读取器。但请注意,由于 MacOSX 中嵌入了颜色管理,目前这些本机图像加载器会提供具有不同像素值的图像。 在 Linux*、BSD 版本和其他类 Unix 开源操作系统上,OpenCV 会寻找操作系统映像提供的编解码器。安装相关软件包(不要忘记开发文件,例如 Debian* 和 Ubuntu* 中的“libjpeg-dev”)以获得编解码器支持或在 CMake 中打开 OPENCV_BUILD_3RDPARTY_LIBS 标志。
我认为基本上 @Dan Mašek 已经在评论部分回答了问题。
我将尝试总结 jpg 文件的发现作为答案,我很高兴看到任何改进。
如果您想从 CMYK 转换 jpg 文件,我们必须查看 grfmt_jpeg.cpp。对于不同的图像代码,还存在其他类似的文件。 根据颜色通道的数量分配
cinfo
。对于 CMYK 图像,cinfo
设置为 4
,并调用 第 504 行 icvCvt_CMYK2Gray_8u_C4C1R
上的函数。void icvCvt_CMYK2Gray_8u_C4C1R( const uchar* cmyk, int cmyk_step,
uchar* gray, int gray_step, Size size )
{
int i;
for( ; size.height--; )
{
for( i = 0; i < size.width; i++, cmyk += 4 )
{
int c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
c = k - ((255 - c)*k>>8);
m = k - ((255 - m)*k>>8);
y = k - ((255 - y)*k>>8);
int t = descale( y*cB + m*cG + c*cR, SCALE );
gray[i] = (uchar)t;
}
gray += gray_step;
cmyk += cmyk_step - size.width*4;
}
}
并使用固定变量进行转换:
#define SCALE 14
#define cR (int)(0.299*(1 << SCALE) + 0.5)
#define cG (int)(0.587*(1 << SCALE) + 0.5)
#define cB ((1 << SCALE) - cR - cG)
如果您的图像仅包含三个颜色通道,则似乎使用 libjpeg 进行转换。这可以在第 717 行中看到。 (我不能 100% 确定这是否是正确的行)。
在jdcolor.c中可以看到,从第41行开始有转换颜色通道的定义和标准。
您的具体问题最重要的部分是:
the conversion equations to be implemented are therefore
R = Y + 1.402 * Cr
G = Y - 0.344136286 * Cb - 0.714136286 * Cr
B = Y + 1.772 * Cb
Y = 0.299 * R + 0.587 * G + 0.114 * B
与 ITU-R 标准相关,并在我发现的许多其他来源中使用。 更详细的信息可以在这里和这里找到。
与 StackOverflow 问题相关的第二个来源清楚地表明,转换不仅取决于纯 RGB 值,还取决于其他参数(如伽玛值)。
OpenCV 使用的标准似乎是 Rec。 601.