简体   繁体   English

PIL 旋转图像 colors (BGR -> RGB)

[英]PIL rotate image colors (BGR -> RGB)

I have an image where the colors are BGR.我有一张图片,其中 colors 是 BGR。 How can I transform my PIL image to swap the B and R elements of each pixel in an efficient manner?如何转换我的 PIL 图像以有效地交换每个像素的 B 和 R 元素?

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

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

Just to add a more up to date answer:只是添加一个更新的答案:

With the new cv2 interface images loaded are now numpy arrays automatically.加载新的 cv2 界面图像现在自动成为 numpy 数组。
But openCV cv2.imread() loads images as BGR while numpy.imread() loads them as RGB.但是 openCV cv2.imread() 将图像加载为 BGR,而 numpy.imread() 将它们加载为 RGB。

The easiest way to convert is to use openCV cvtColor.最简单的转换方法是使用 openCV cvtColor。

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

Assuming no alpha band, isn't it as simple as this?假设没有alpha波段,是不是就这么简单?

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

Edit:编辑:

Hmm... It seems PIL has a few bugs in this regard... im.split() doesn't seem to work with recent versions of PIL (1.1.7).嗯...似乎 PIL 在这方面有一些错误... im.split()似乎不适用于最新版本的 PIL (1.1.7)。 It may (?) still work with 1.1.6, though...它可能 (?) 仍然适用于 1.1.6,不过......

Adding a solution using the ellipsis使用省略号添加解决方案

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

In this case, the ellipsis ... is equivalent to :,: while ::-1 inverts the order of the last dimension (channels).在这种情况下,省略号...等效于:,:::-1反转最后一个维度(通道)的顺序。

This was my best answer.这是我最好的答案。 This does, by the way, work with Alpha too.顺便说一下,这也适用于 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)

Just to clarify Martin Beckets solution, as I am unable to comment.只是为了澄清 Martin Beckets 的解决方案,因为我无法发表评论。 You need cv2.你需要cv2。 in front of the color constant.前面的颜色不变。

im = Image.frombuffer('RGB', (width, height), bgr_buf, 'raw', 'BGR', 0, 0)

Using the ideas explained before... using numpy you could.使用之前解释过的想法......使用 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')

Additionally it can remove the Alpha channel.此外,它还可以删除 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

Application of other solutions.其他解决方案的应用。 Just for a temporary measure.只是为了临时措施。

import numpy

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

Just a quick footnote for anyone writing code that might have to deal with 4-channel images, and discovering that the simple numpy answer seems to be eating their alpha channel.对于编写可能必须处理 4 通道图像的代码并发现简单的 numpy 答案似乎正在吞噬他们的 alpha 通道的任何人来说,这只是一个快速的脚注。

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

will preserve the alpha data if there is a fourth channel, whereas如果有第四个通道,将保留 alpha 数据,而

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

will overwrite the 4-channel image with only reversed 3-channel data.将仅用反转的 3 通道数据覆盖 4 通道图像。 (And the even simpler numpy answer, img = img[:,:,::-1], will give you ARGB data, which would be bad, too. :) (还有更简单的 numpy 答案,img = img[:,:,::-1],会给你 ARGB 数据,这也会很糟糕。:)

You should be able to do this with the ImageMath module.您应该能够使用ImageMath模块执行此操作。

Edit:编辑:

Joe's solution is even better, I was overthinking it.乔的解决方案更好,我想多了。 :) :)

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


Speed comparison:速度对比:

%%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)

Problem is, OP ask if img is already in PIL image format, whereas cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) require img in numpy array format.问题是,OP 询问img是否已经是PIL图像格式,而cv2.cvtColor(img, cv2.COLOR_BGR2RGB))需要numpy数组格式的img

But, cv2.imread() is most likely the reason you got BGR image.但是, cv2.imread()很可能是您获得 BGR 图像的原因。 Not Image.open() .不是Image.open()

If you have an alpha band, use this:如果您有 alpha 波段,请使用:

img = img[:,:, [2, 1, 0, 3]]

Flip channels the way you want!随心所欲地切换频道!

# You source order
source = 'BGR'

# The order you want
target = 'RGB'

# Grab the indices of channel in last dimension
image = image[...,[target.index(s) for s in source]]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM