将图像数据转换为 unsigned int 类型以用于 OpenCV 的问题

Problems converting image data to unsigned int types for use with OpenCV

我有一个 8 位 .gif 图像,我可以将其读入 dtype uint8 的 Numpy 数组。但是,当我尝试将 dtype 转换为更大的整数类型时,例如 uint32uint64,以便在 OpenCV 中使用,我得到了奇怪的错误。

我正在使用 Google Colab 并且是 运行 Python 3.6.

我下载了这张 8 位彩色 gif 图片:

!wget https://www.cosy.sbg.ac.at/~pmeerw/Watermarking/lena_color.gif

下面是我的代码,我尝试将图像转换为每个 [ np.uint8, np.uint16, np.uint32, np.uint64 ],然后绘制一个矩形。

import numpy as np
import cv2
import matplotlib

print(np.__version__)          # 1.19.5
print(cv2.__version__)         # 4.1.2
print(matplotlib.__version__)  # 3.2.2

import matplotlib.pyplot as plt
import matplotlib.image as mpimg


img_orig = mpimg.imread('lena_color.gif')
print('img_orig dtype: %s' % img_orig.dtype) # img_orig dtype: uint8

# Coordinates for rectangle to be drawn.
TL = (100, 100)
BR = (400, 400)

# Convert to different integer dtypes.
dtypes = [ np.uint8, np.uint16, np.uint32, np.uint64 ]

for dtype in dtypes:

    print('Changing type to %s' % (dtype.__name__))

    img = img_orig.astype(dtype)
    try:
        cv2.rectangle(img, TL, BR, (0, 0, 255), 2)
        _ = plt.imshow(img)
        _ = plt.show()
    except Exception as ex:
        print(ex)

我得到以下结果:

Changing type to uint8

Changing type to uint16

Changing type to uint32
an integer is required (got type tuple)
Changing type to uint64

具体问题:

  1. 为什么我将 dtype 更改为 uint32 时会出现异常?

  2. 我用蓝色画了矩形(0, 0, 255)。为什么矩形会以 white-purple 的形式出现?

  3. 为什么dtype为uint64时矩形没有出现?

您的图片有 alpha 通道。这意味着每个像素有 4 个分量(R、G、B、A),而不仅仅是三个。您应该打印图像数组以查看它们包含的内容。当您指定 (0,0,255) 时,它默认为 0 作为 alpha。这意味着您正在看到背景显示。矩形将是当时背景 window 的任何颜色。如果您指定 (0,0,255,255),您将看到您期望的蓝色。

另请注意,更改 numpy 数组的数据类型实际上没有任何用处。无论组件的数据类型如何,组件都取 0 到 255 之间的值。

这里发生了几件事。首先,您正在使用 OpenCVmatplotlib。这些是不同的图像库,它们之间并非 100% 兼容。 OpenCV 使用 BGR 颜色通道排序,而 matplotlib 使用 RGB。如果您使用 OpenCV(例如 cv2.rectangle)中的函数处理图像,则期望在反向通道上运行,如果您使用 matplotlib.

加载或显示图像

现在,请回答您的第一个问题。图像类型通常使用每个通道 8 个无符号位进行编码。这是 BGR(或 RGB)图像的 8 x 3 位,尽管您也可以为灰度图像设置 8 x 1 位,或者 [=26] 的 8 x 4 位=](最后一个通道是 Alpha 通道 - 透明通道。这些情况之外的每种类型都可能不受一组函数的支持。在 OpenCV 的情况下,cv2.rectangle 不支持数组类型 uint32uint64。事实上,我在使用这两种格式时都遇到了异常。

现在,矩形。您使用 OpenCV 绘制矩形并使用 matplotlib 显示它,因此期望您在矩形函数上设置的颜色与您在屏幕上看到的颜色不匹配。特别是,此图像文件是一个 .gif 具有额外透明通道的图像,使其成为 RGBA(4 个通道)图像。您正在使用三个参数设置颜色,但是,cv2.rectangle 似乎只影响 alpha 通道,将其设置为 255。解决方案是使用 cv2.cvtColor:

RGBA 图像转换为 RGB 图像
# Include this line just before drawing the rectangle:
# Conversion from RGBA to RGB:
img = cv2.cvtColor(img, cv2.COLOR_RGBA2RGB)

因此您将在屏幕上看到正确的结果:

建议:

  1. 如果您要使用多个图像库,请注意它们的差异和可能的兼容性问题

  2. 仅操作显示BGRRGB图像,其他类型通常是中间操作时间结果

  3. 如果处理 .gifs,请检查他们使用了多少频道。图像(至少 OpenCV 需要它们)表示为 numpy 数组。您可以使用 shape

    检查 numpy 数组的维度

像这样:

(height, width, channels) = img.shape
print((height, width, channels))

对于 Lena 图像,此 returns:

(512, 512, 4)