【问题标题】:PIL rotate image colors (BGR -> RGB)PIL 旋转图像颜色 (BGR -> RGB)
【发布时间】:2011-06-07 09:19:09
【问题描述】:

我有一张颜色为 BGR 的图像。如何转换我的 PIL 图像以有效地交换每个像素的 B 和 R 元素?

【问题讨论】:

    标签: python colors python-imaging-library


    【解决方案1】:

    我知道这是一个老问题,但我遇到了同样的问题并解决了:

    img = img[:,:,::-1]
    

    【讨论】:

    • 数据有3个维度:宽度、高度和颜色。 ::-1 有效地颠倒了颜色的顺序。宽度和高度不受影响。
    • 好,我是按照你的笔记和我的测试得到的。::-1实际上是numpy操作[start:end:step]的简写,start/end是自动决定的。
    • 为了清楚起见,img = img[:, :, : :-1] 等价于 img = img[:, :, [2,1,0]]。我认为后者更好,因为它更明确。
    • img[:, :, : :-1] 不等同于 img[:, :, [2,1,0]]。前者使用基本索引,后者使用高级索引。后者会复制您的图像,而前者不会。
    • 这也比上面答案中建议的 cv2.cvtColor 函数性能要好得多。
    【解决方案2】:

    只是添加一个更新的答案:

    使用新的 cv2 界面加载的图像现在自动成为 numpy 数组。
    但是 openCV cv2.imread() 将图像加载为 BGR,而 numpy.imread() 将它们加载为 RGB。

    最简单的转换方法是使用openCV cvtColor。

    import cv2
    srcBGR = cv2.imread("sample.png")
    destRGB = cv2.cvtColor(srcBGR, cv2.COLOR_BGR2RGB)
    

    【讨论】:

    • 您拥有 BGR 图像的唯一原因几乎是您使用的是 OpenCV。您的解决方案是正确的做法。另一个最佳答案是功能性的,但在处理大图像时会很慢。
    • 为什么这个不在上面?
    • 因为最简单的解决方案实际上就是:img = img[..., ::-1]
    • cv2 是否保证图像是连续的? OpencCV(至少在 c++ 中)将在 4 字节边界上开始每个新行,因此您必须小心移动原始字节
    • 感谢...我在相同的代码中使用它们,让我疯狂了一段时间@RyanSoklaski 这实际上更令人困惑,不知道哪个是 opencv 或 PIL 的默认值,但非常整洁跨度>
    【解决方案3】:

    假设没有 alpha 波段,是不是就这么简单?

    b, g, r = im.split()
    im = Image.merge("RGB", (r, g, b))
    

    编辑:

    嗯...似乎 PIL 在这方面有一些错误...im.split() 似乎不适用于最新版本的 PIL (1.1.7)。它可能(?)仍然适用于 1.1.6,不过...

    【讨论】:

    • 解决方案是首先正确加载图像 =P 但这看起来很可爱
    • np.roll 会将 BGR 转换为 RBG,而不是 RGB。如果您想在 numpy 中执行此操作,可以使用 data[...,[2,1,0]] 交换频道。但是,如果您已经在使用 OpenCV 或 PIL,请按照 Martin Beckett 的回复。
    • @LukeYeager 建议的另一个 numpy 替代方案:np.flip(image_bgr, axis=2)
    【解决方案4】:

    使用省略号添加解决方案

    image = image[...,::-1]

    在这种情况下,省略号... 等效于:,:,而::-1 反转了最后一个维度(通道)的顺序。

    【讨论】:

      【解决方案5】:

      这是我最好的答案。顺便说一句,这也适用于 Alpha。

      from PIL import Image
      import numpy as np
      import sys 
      
      sub = Image.open(sys.argv[1])
      sub = sub.convert("RGBA")
      data = np.array(sub) 
      red, green, blue, alpha = data.T 
      data = np.array([blue, green, red, alpha])
      data = data.transpose()
      sub = Image.fromarray(data)
      

      【讨论】:

        【解决方案6】:
        import cv2
        srcBGR = cv2.imread("sample.png")
        destRGB = cv2.cvtColor(srcBGR,cv2.COLOR_BGR2RGB)
        

        只是为了澄清 Martin Beckets 的解决方案,因为我无法发表评论。 你需要cv2。在颜色常数前面。

        【讨论】:

        • 很有用,谢谢。请注意,您可以提出修改建议,如果获得批准,您将获得 +2 代表
        • 谢谢,克劳迪乌,我会试试看:“”“编辑必须至少有 6 个字符;这篇文章还有什么需要改进的地方吗?”“” ;-)
        【解决方案7】:

        对于编写可能必须处理 4 通道图像的代码并发现简单的 numpy 答案似乎正在吞噬他们的 alpha 通道的任何人来说,这只是一个快速脚注。

        np_image[:,:,[0,1,2]] = np_image[:,:,[2,1,0]]
        

        如果有第四个通道,将保留 alpha 数据,而

        np_image = np_image[:,:,[2,1,0]]
        

        将仅使用反转的 3 通道数据覆盖 4 通道图像。 (更简单的 numpy 答案,img = img[:,:,::-1],会给你 ARGB 数据,这也很糟糕。:)

        【讨论】:

          【解决方案8】:
          im = Image.frombuffer('RGB', (width, height), bgr_buf, 'raw', 'BGR', 0, 0)
          

          【讨论】:

          • 你能详细说明你的答案吗?因为显然你需要使用np.shape 或类似的东西来获取维度。还有bgr_buf是什么?
          【解决方案9】:

          使用之前解释的想法...使用 numpy 可以。

          bgr_image_array = numpy.asarray(bgr_image)
          B, G, R = bgr_image_array.T
          rgb_image_array = np.array((R, G, B)).T
          rgb_image = Image.fromarray(rgb_image_array, mode='RGB')
          

          另外它可以去除Alpha通道。

          assert bgra_image_array.shape == (image_height, image_width, 4)
          B, G, R, _ = bgra_image_array.T
          rgb_image_array = np.array((R, G, B)).T
          

          【讨论】:

            【解决方案10】:

            其他解决方案的应用。只是临时措施。

            import numpy
            
            im = Image.fromarray(numpy.array(im)[:,:,::-1])
            

            【讨论】:

            • 这是我通常的做法,虽然如果它有 alpha Image.fromarray(np.array(img)[:,:,:3][:,:,::-1])
            【解决方案11】:

            您应该可以使用ImageMath 模块来做到这一点。

            编辑:

            Joe 的解决方案更好,我想多了。 :)

            【讨论】:

              【解决方案12】:

              TLDR:如果您已经导入 cv2,请使用 cv2.cvtColor(img, cv2.COLOR_BGR2RGB))


              速度对比:

              %%timeit
              img_ = Image.fromarray(img[...,::-1])
              # 5.77 ms ± 12.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
              
              %%timeit
              img_ = Image.fromarray(img[...,[2,1,0]])
              # 6.2 ms ± 2.43 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
              
              %%timeit
              img_ = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
              # 442 µs ± 4.84 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
              

              问题是,OP 询问 img 是否已经采用 PIL 图像格式,而 cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) 要求 img 采用 numpy 数组格式。

              但是,cv2.imread() 很可能是您获得 BGR 图像的原因。不是Image.open()

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2021-08-05
                • 1970-01-01
                • 1970-01-01
                • 2013-01-15
                • 1970-01-01
                • 1970-01-01
                • 2021-03-10
                相关资源
                最近更新 更多