【发布时间】:2011-06-07 09:19:09
【问题描述】:
我有一张颜色为 BGR 的图像。如何转换我的 PIL 图像以有效地交换每个像素的 B 和 R 元素?
【问题讨论】:
标签: python colors python-imaging-library
我有一张颜色为 BGR 的图像。如何转换我的 PIL 图像以有效地交换每个像素的 B 和 R 元素?
【问题讨论】:
标签: python colors python-imaging-library
我知道这是一个老问题,但我遇到了同样的问题并解决了:
img = img[:,:,::-1]
【讨论】:
::-1 有效地颠倒了颜色的顺序。宽度和高度不受影响。
::-1实际上是numpy操作[start:end:step]的简写,start/end是自动决定的。
只是添加一个更新的答案:
使用新的 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)
【讨论】:
假设没有 alpha 波段,是不是就这么简单?
b, g, r = im.split()
im = Image.merge("RGB", (r, g, b))
编辑:
嗯...似乎 PIL 在这方面有一些错误...im.split() 似乎不适用于最新版本的 PIL (1.1.7)。它可能(?)仍然适用于 1.1.6,不过...
【讨论】:
np.roll 会将 BGR 转换为 RBG,而不是 RGB。如果您想在 numpy 中执行此操作,可以使用 data[...,[2,1,0]] 交换频道。但是,如果您已经在使用 OpenCV 或 PIL,请按照 Martin Beckett 的回复。
np.flip(image_bgr, axis=2)
使用省略号添加解决方案
image = image[...,::-1]
在这种情况下,省略号... 等效于:,:,而::-1 反转了最后一个维度(通道)的顺序。
【讨论】:
这是我最好的答案。顺便说一句,这也适用于 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)
【讨论】:
import cv2
srcBGR = cv2.imread("sample.png")
destRGB = cv2.cvtColor(srcBGR,cv2.COLOR_BGR2RGB)
只是为了澄清 Martin Beckets 的解决方案,因为我无法发表评论。 你需要cv2。在颜色常数前面。
【讨论】:
对于编写可能必须处理 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 数据,这也很糟糕。:)
【讨论】:
im = Image.frombuffer('RGB', (width, height), bgr_buf, 'raw', 'BGR', 0, 0)
【讨论】:
np.shape 或类似的东西来获取维度。还有bgr_buf是什么?
使用之前解释的想法...使用 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
【讨论】:
其他解决方案的应用。只是临时措施。
import numpy
im = Image.fromarray(numpy.array(im)[:,:,::-1])
【讨论】:
Image.fromarray(np.array(img)[:,:,:3][:,:,::-1])
【讨论】:
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()。
【讨论】: