53

我在 Ubuntu 12.04 上使用 Python (2.7) 和 OpenCV 2.4.6 的绑定

我加载图像

    image = cv2.imread('image.jpg')

然后我检查图像阵列的形状

    print image.shape

我得到 (480, 640, 3),这是我期望的 640x480 彩色图像。然后我将图像转换为灰度并再次检查形状。

    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    print gray_image.shape

我得到 (480, 640, 1),这是我期望的 640x480灰度图像。然后我保存图像:

    cv2.imwrite('gray.jpg', gray_image)

我在 linux 上,所以我尝试使用 gThumb 查看图像,它显示了所有颜色通道。当我将灰色图像带回 OpenCV 时,图像再次具有三个通道。我知道这个用于读取图像的标志:

    CV_LOAD_IMAGE_GRAYSCALE - If set, always convert image to the grayscale one

但这听起来像是要将图像作为彩色图像引入,然后进行转换。我正在将此项目移植到 RaspberryPi,因此我不希望发生不必要的操作。

编辑:我做了一些时间检查,我发现使用 CV_LOAD_IMAGE_GRAYSCALE 标志集加载图像会导致图像加载速度提高两倍,而与图像输入无关。

     Using a 3072 x 4608 x 3 image
     0.196774959564 seconds with default loading
     0.0931899547577 seconds with CV_LOAD_IMAGE_GRAYSCALE

问题似乎是 OpenCV 正在创建一个 3 通道 JPG 输出,无论我是否有灰度图像矩阵!

我可以使用什么其他应用程序来确保我得到一个 8 位通道的 JPG 图像?(也许 gThumb 错误地报告了频道)。

如果图像不是单通道,为什么 OpenCV 在磁盘写入时将我的灰度图像保存为 3 通道图像?

提前致谢。

4

4 回答 4

76

您的代码是正确的,除非设置,否则似乎cv2.imread加载具有三个通道的图像。CV_LOAD_IMAGE_GRAYSCALE

>>> import cv2
>>> image = cv2.imread('foo.jpg')
>>> print image.shape
 (184, 300, 3)
>>> gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
>>> print gray_image.shape 
 (184, 300)
>>> cv2.imwrite('gray.jpg', gray_image)

现在,如果您加载图像:

>>> image = cv2.imread('gray.jpg')
>>> print image.shape
 (184, 300, 3)

似乎您已将图像保存为 BGR,但事实并非如此,它只是 opencv,默认情况下它读取具有 3 个通道的图像,如果它是灰度的,它会将其图层复制 3 次。如果您再次使用 scipy 加载图像,您会看到图像确实是灰度的:

>>> from scipy.ndimage import imread
>>> image2 = imread('gray.jpg')
>>> print image2.shape
 (184, 300)

因此,如果要加载灰度图像,则需要设置CV_LOAD_IMAGE_GRAYSCALE标志:

>>> image = cv2.imread('gray.jpg', cv2.CV_LOAD_IMAGE_GRAYSCALE)
>>> print image.shape
 (184, 300)
于 2013-09-18T11:46:39.173 回答
21

尝试这个:

 img = cv2.imread('gray.jpg',0)

0代表灰色,1代表彩色

于 2017-07-20T12:17:33.997 回答
3

在 openCV 读取 jpg 图像时,默认情况下会产生 3 通道图像。所以我不确定你是否真的可以从 jpg 文件中看到它已经是灰度的,但你总是可以将它加载为灰度。仅当图像未事先进行灰度化时才会带来问题,并且对于您的情况,我相信它不起作用。如此简短的回答:您不能将 jpg 保存为单通道图像。因此,您需要在阅读后再次对其进行灰度化或找出确定图像是否为灰度的新方法。

于 2013-09-18T11:44:14.900 回答
0

如果您想保留原始通道数,同时使用 OpenCV 加载图像(正如@Gall 的评论中已经提到的):

img_np = cv2.imread("path/to_img", cv2.IMREAD_UNCHANGED)

cv2.IMREAD_GRAYSCALE- 将所有内容转换为灰度。

如果您还想保留原始深度(即int16),而不是隐式int8转换(默认情况下):

img_np = cv2.imread(image_path, cv2.IMREAD_ANYDEPTH | cv2.IMREAD_UNCHANGED)
于 2021-07-31T18:30:23.913 回答