Python - 使用 OpenCV 将图像保存在文件中后,窗口中的图像外观有所不同

标签 python python-3.x opencv rgb opencv3.0

我在下面有这段代码:

cv2.imshow('RGB Transform Image', rgb_transform)
cv2.waitKey()
cv2.imwrite('rgb_transformed_image', rgb_transform )

当我显示图像时,它如下所示:

enter image description here

但是查看保存文件后,图像如下所示:

enter image description here

太奇怪了。我哪里做错了?

更新 :

我的代码的上下文是我已将图像读取为灰度,拆分其 RGB 然后在每个 channel 上执行转换,然后再次组合它。
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
image = imutils.resize(image, width = 500)

a = 255
b = 2 * (np.pi/255)
c = np.pi / 5

R = a * np.absolute(np.sin(b * image))
G = a * np.absolute(np.sin(b * image + c))
B = a * np.absolute(np.sin(b * image + 2 * c))

rgb_transform =  np.stack((R,G,B),2)

cv2.imshow('RGB Transform Image', rgb_transform)    
cv2.waitKey()
cv2.imwrite('rgb_transformed_image', rgb_transform )

最佳答案

当你给 cv2.imshow 时,往往会出现这种问题。和 cv2.imwrite除了具有 uint8 类型元素的数组之外的其他东西.

函数 cv2.imshow 在显示图像之前进行一些转换(缩放):

The function may scale the image, depending on its depth:

  • If the image is 8-bit unsigned, it is displayed as is.
  • If the image is 16-bit unsigned or 32-bit integer, the pixels are divided by 256. That is, the value range [0,255*256] is mapped to [0,255].
  • If the image is 32-bit or 64-bit floating-point, the pixel values are multiplied by 255. That is, the value range [0,1] is mapped to [0,255].


即使文档不是很清楚, cv2.imwrite 不做任何缩放。最多它会转换为 uint8 ,但从来没有任何缩放。

让我们来看看你的问题所在。你执行类似的操作a * np.absolute(np.sin(b * image))在包含 [0,255] 范围内的值的输入图像上。这些操作的结果是一个 64 位浮点值数组( np.float64 ,或在 OpenCV 中 CV_64F )。经检查,值的范围仍为 [0.0,255.0]。

即使文档似乎没有明确提到这一点,cv2.imshow将像处理 32 位浮点数一样处理 64 位浮点数 - 即它会将值缩放 255(饱和度),然后将它们显示为 3 channel 8 位 BGR 图像。这意味着源图像中强度 > 1 的任何内容都会被剪裁,您会看到大部分是白色像素。

正如我之前提到的,cv2.imwrite不做任何缩放,它只会将数据类型转换为它可以使用的东西并保存一个看起来合理的图像。

此问题的解决方案是将浮点值四舍五入为最接近的整数(因此您使用完整范围)并将结果转换为 np.uint8 , 在您将其传递给 cv2.imwrite 之前或 cv2.imshow :
rgb_transform = np.uint8(np.around(rgb_transform))

作为一般建议,了解您将哪种数据传递给您使用的各种函数并将其与文档交叉引用非常有用。

使用 numpy 数组时,数组的以下几个属性对检查很有用(我将根据您的 rgb_transform 说话,请随意替换变量名):
  • rgb_transform.shape -- channel 大小和数量
  • rgb_transform.dtype -- 每个元素的数据类型
  • rgb_transform.min() -- 数组中的最小值
  • rgb_transform.max() -- 数组中的最大值

  • 当您遇到问题时,最好检查它们的值(在交互式解释器中,或者说使用简单的打印语句)。了解您输入其他函数的数据并将其与文档交叉引用非常重要。

    关于Python - 使用 OpenCV 将图像保存在文件中后,窗口中的图像外观有所不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49770419/

    相关文章:

    opencv - 无法绘制最大轮廓

    python - 如何对数据集子集重复相同的操作

    python - 将带有撇号的单词计为一个单词但返回两个单词(python)

    python - 无法在 Anaconda 4.3 中安装 OpenCV 3.2

    python - 在一行中打印 for 循环结果并排序

    opencv - 3 台固定摄像机的 3D 图像重建?

    python - 在 XCode 4 中运行 PyObjC 模板时发生泄漏

    python - 如何在 Python 2.5 中将异常分配给局部变量?

    python - 编辑 Python 绘图表面刻度及其频率

    c++ - 如何计算两点之间的角度并以此为基础旋转第三点?