PIL rotate image colors (BGR -> RGB)

112,744

Solution 1

Assuming no alpha band, isn't it as simple as this?

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). It may (?) still work with 1.1.6, though...

Solution 2

I know it's an old question, but I had the same problem and solved it with:

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

Solution 3

Just to add a more up to date answer:

With the new cv2 interface images loaded are now numpy arrays automatically.
But openCV cv2.imread() loads images as BGR while numpy.imread() loads them as RGB.

The easiest way to convert is to use openCV cvtColor.

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

Solution 4

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

Solution 5

This was my best answer. This does, by the way, work with Alpha too.

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)
Share:
112,744
Claudiu
Author by

Claudiu

Graduated from Brown University. E-mail: [email protected]

Updated on July 05, 2022

Comments

  • Claudiu
    Claudiu almost 2 years

    I have an image where the colors are BGR. How can I transform my PIL image to swap the B and R elements of each pixel in an efficient manner?

  • Claudiu
    Claudiu over 13 years
    the solution was to load the image properly in the first place =P but this seems lovely
  • Claudiu
    Claudiu over 10 years
    Ah useful, thanks. Note you can suggest an edit and you get +2 rep if it gets approved
  • user2692263
    user2692263 over 10 years
    thanks, Claudiu, I'll try that: """Edits must be at least 6 characters; is there something else to improve in this post?""" Well - that did not go so well ;-)
  • Zach Garner
    Zach Garner over 9 years
    Pretty much the only reason you would have a BGR image is if you're using OpenCV. Your solution is the right thing to do. The other top answer is functional, but would be slow in processing large images.
  • Luke Yeager
    Luke Yeager about 9 years
    np.roll will convert BGR to RBG, not RGB. If you want to do this in numpy, you can use data[...,[2,1,0]] to swap the channels. But if you're already using OpenCV or PIL, just go with Martin Beckett's response.
  • Peter9192
    Peter9192 over 7 years
    The data has 3 dimensions: width, height, and color. ::-1 effectively reverses the order of the colors. The width and height are not affected.
  • Wesley Ranger
    Wesley Ranger over 7 years
    Good, I got it following your note and my testing.::-1 is actually a shorthand of numpy operation [start:end:step], and start/end is decided automatically.
  • DollarAkshay
    DollarAkshay about 7 years
    Why is this not on top ?
  • Ryan Soklaski
    Ryan Soklaski almost 7 years
    Because the simplest solution is literally just: img = img[..., ::-1]
  • Martin Beckett
    Martin Beckett almost 7 years
    Does cv2 guarantee that images are contiguous? OpencCV (at least in c++) will start each new row on a 4byte boundary so you have to be careful moving raw bytes around
  • Eliethesaiyan
    Eliethesaiyan almost 7 years
    thanks for this...i am using them in the same codes,got me crazy for a while@RyanSoklaski that is actually more confusing without knowing which is default for opencv or PIL but very neat
  • EuWern
    EuWern about 6 years
    for clarity, img = img[:, :, : :-1] is equivalent to img = img[:, :, [2,1,0]]. I think the later is better as it is more explicit.
  • Ryan Soklaski
    Ryan Soklaski almost 6 years
    img[:, :, : :-1] is not equivalent to img[:, :, [2,1,0]]. The former utilizes basic index and the latter uses advanced indexing. The latter will make a copy of your image while the former does not.
  • Vinícius M
    Vinícius M almost 5 years
    This is also significantly more performant than the cv2.cvtColor function suggested in an answer above.
  • hoohoo-b
    hoohoo-b over 4 years
    Another numpy alternative to @LukeYeager's suggestion: np.flip(image_bgr, axis=2)
  • Lewis Morris
    Lewis Morris over 3 years
    This is how I do it usually, Although if its got alpha Image.fromarray(np.array(img)[:,:,:3][:,:,::-1])
  • Muhammad Yasirroni
    Muhammad Yasirroni over 2 years
    Can you elaborate your answer? Because obviously you need to use np.shape or someting like that to get the dimension. Also what is bgr_buf?