【问题标题】:In OpenCV (Python), why am I getting 3 channel images from a grayscale image?在 OpenCV (Python) 中,为什么我从灰度图像中获取 3 通道图像?
【发布时间】:2013-09-23 02:48:03
【问题描述】:

我在 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 通道图像?

提前致谢。

【问题讨论】:

    标签: python opencv image-processing jpeg grayscale


    【解决方案1】:

    如果您想在使用 OpenCV 加载图像时保留原始通道数(正如 @Gall 在 cmets 中已经提到的那样):

    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)
    

    【讨论】:

      【解决方案2】:

      试试这个:

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

      0 表示灰色,1 表示颜色

      【讨论】:

      • 这仍然会给你 3 个频道
      • @Oeyvind,不,它会给你 1 个频道,但即使最初 PNG 有 3 个频道。
      【解决方案3】:

      您的代码是正确的,似乎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)
      

      【讨论】:

      • 谢谢,gThumb 似乎也复制了图层。
      • 说了这么多,单通道格式保存图片的解决方案是什么? (假设我们必须在单通道中保存图像)
      • 看起来 cv2.IMREAD_GRAYSCALE 是这些天要走的路,而不是 cv2.CV_LOAD_IMAGE_GRAYSCALE
      • 补充一点,我认为cv2.IMREAD_UNCHANGED 每次使用都很安全。
      • 对于使用 jupytermatplotlib this 的任何人,我免于发疯。也就是说,即使是灰度图像,plt.imshow() 还是会使用颜色来增强对比度。使用plt.imshow(img, cmap='Greys_r') 覆盖。
      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-01-19
        • 2018-03-29
        • 2011-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多