为什么cv2.imwrite()会改变图片的颜色?

65

我有以下这段代码:

imgs = glob.glob('/home/chipin/heart/tray.png')
current_img = io.imread(imgs[0])
cv2.imwrite('/home/chipin/heart/01.png', current_img[0:511,0:511])  

图片大小为512*512,保存后,蓝色图片变成了黄色。似乎有一个通道被舍弃了。我真的不知道为什么。

这是current_img的值:

current_img的值


我假设 io.imread 是来自 skimage 的函数? - Dan Mašek
6
如果是这样的话,问题在于skimage.io.imread将图像加载为RGB格式,但是numpy假定图像为BGR,因此蓝色和红色平面会翻转。 为什么不直接使用cv2.imread加载图像呢? - Dan Mašek
2
要么使用cv2.imread,它会以BGR格式读取(这是OpenCV的默认格式),或者使用cv2.cvtColor将RGB转换为BGR。 - Dan Mašek
非常感谢你。 - StalkerMuse
OpenCV选择将RGB通道进行交换的原因是什么?增加复杂性的理由是什么:已经有足够多的颜色空间了:RGB、LAB、CMYK、HUV...为什么还要创建BGR呢?:) 你知道这个历史原因吗,@DanMašek? - undefined
显示剩余3条评论
2个回答

146

您的问题在于,skimage.io.imread将图像加载为RGB(或RGBA),但OpenCV假定图像是BGR或BGRA(BGR是默认的OpenCV颜色格式)。这意味着蓝色和红色平面会被翻转。


3通道图像

让我们使用以下简单的测试图像进行尝试:

输入图像


首先让我们尝试您原始的算法:

import skimage.io
import cv2

img = skimage.io.imread('sample.png')
cv2.imwrite('sample_out_1.png', img)

我们得到了以下结果:

Result 1

如您所见,红色和蓝色通道明显被交换了。


第一种方法,假设您仍然想使用skimage读取和cv2写入,则可以使用cv2.cvtColor将RGB转换为BGR。

由于新的OpenCV文档没有提及Python语法,在这种情况下,您还可以使用适用于2.4.x的相应参考文献

import skimage.io
import cv2

img = skimage.io.imread('sample.png')
cv2.imwrite('sample_out_2.png', cv2.cvtColor(img, cv2.COLOR_RGB2BGR))    

现在我们获得以下输出:

结果2


另一种选择是只使用OpenCV -- 使用cv2.imread 来加载图像。在这种情况下,我们仅处理BGR图像。

NB: 不提供任何标志意味着默认使用cv2.IMREAD_COLOR -- 即图像始终被加载为三通道图像(丢弃任何潜在的alpha通道)。

import cv2

img = cv2.imread('sample.png')
cv2.imwrite('sample_out_3.png', img)

Result 3


4通道图像

根据您的截图,似乎您有一张4通道图像。这意味着在skimage中是RGBA,在OpenCV中是BGRA。原理类似。

  • 要么使用颜色转换代码 cv2.COLOR_RGBA2BGRA
  • 要么使用标志 cv2.IMREAD_UNCHANGEDcv2.imread

嗯,也许我不应该让示例图像具有旋转对称性。 :) - Dan Mašek
在使用cv2.imread读取图片,但使用matplotlib显示时,我发现这很有用。不过,我觉得奇怪的是opencv使用BGR。 - Lem Ko
好的,请阅读这个链接:https://www.learnopencv.com/why-does-opencv-use-bgr-color-format/。显然,OpenCV使用BGR是因为马的屁股。 - Lem Ko
1
@DanMašek 解释得很清楚,谢谢。 - Innat

3

输入的图像(以png格式)是按RGB顺序排列的,但在内存中(作为cv :: Mat),它是按BGR顺序排列的。

使用 cv2.imread()进行输入。因此,imread()将在幕后内部从rgb转换为bgr,而imwrite()将执行相反的操作。

以下是具体实现方法:

current_img = cv2.imread('/home/chipin/heart/tray.png')
cv2.imwrite('/home/chipin/heart/01.png', current_img)  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接