Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to swap blue and red channel in an image using OpenCV

Tags:

python

opencv

I am facing a little bit of problem in swapping the channels (specifically red and blue) of an image. I am using Opencv 3.0.0 and Python 2.7.12. Following is my code for swapping the channels

import cv2

img = cv2.imread("input/car1.jpg")

#The obvious approach
Cimg = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

#Manual Approach
red = img[:,:,2]
blue = img[:,:,0]

img[:,:,0] = red
img[:,:,2] = blue

cv2.imshow("frame",Cimg)
cv2.imshow("frame2", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

I am unable to figure out why the same image undergoing through the same(probably) operation is giving two different outputs. Can someone throw some light on what's going wrong?

Original Image The original Image

Manual Operation The manual operation

COLOR_BGR2RGB The cv2.COLOR_BGR2RGB operation

like image 798
Shashwat Verma Avatar asked Jul 23 '16 06:07

Shashwat Verma


People also ask

How do I separate RGB channels in OpenCV?

In OpenCV, BGR sequence is used instead of RGB. This means the first channel is blue, the second channel is green, and the third channel is red. To split an RGB image into different channels, we need to define a matrix of 3 channels. We use 'Mat different_Channels[3]' to define a three-channel matrix.

How do I split a color image into its 3 RGB channels in Python?

Image. split() method is used to split the image into individual bands. This method returns a tuple of individual image bands from an image. Splitting an “RGB” image creates three new images each containing a copy of one of the original bands (red, green, blue).


1 Answers

red and blue are just views of your image. When you do img[:,:,0] = red this changes img but also blue which is just a view (basically just a reference to the sub-array img[:,:,0]) not a copy, so you loose the original blue channel values. Basically what you assume is a temp copy just is not. Add .copy() and it will work.

img = np.arange(27).reshape((3,3,3))

red = img[:,:,2].copy()
blue = img[:,:,0].copy()

img[:,:,0] = red
img[:,:,2] = blue

print("with copy:\n", img)

img = np.arange(27).reshape((3,3,3))

red = img[:,:,2]
blue = img[:,:,0]

img[:,:,0] = red
img[:,:,2] = blue

print("without copy:\n",img)

results:

with copy:

 [[[ 2  1  0]
  [ 5  4  3]
  [ 8  7  6]]

 [[11 10  9]
  [14 13 12]
  [17 16 15]]

 [[20 19 18]
  [23 22 21]
  [26 25 24]]]

without copy:

 [[[ 2  1  2]
  [ 5  4  5]
  [ 8  7  8]]

 [[11 10 11]
  [14 13 14]
  [17 16 17]]

 [[20 19 20]
  [23 22 23]
  [26 25 26]]]

Note: you actually only need 1 temp copy of 1 channel. Or you could also simply do img[:,:,::-1] this will create a view again but with swapped channels, img will stay unchanged, unless you reassign it:

img = np.arange(27).reshape((3,3,3))

print(img[:,:,::-1])
print(img)
img = img[:,:,::-1]
print(img)

results:

[[[ 2  1  0]
  [ 5  4  3]
  [ 8  7  6]]

 [[11 10  9]
  [14 13 12]
  [17 16 15]]

 [[20 19 18]
  [23 22 21]
  [26 25 24]]]


[[[ 0  1  2]
  [ 3  4  5]
  [ 6  7  8]]

 [[ 9 10 11]
  [12 13 14]
  [15 16 17]]

 [[18 19 20]
  [21 22 23]
  [24 25 26]]]


[[[ 2  1  0]
  [ 5  4  3]
  [ 8  7  6]]

 [[11 10  9]
  [14 13 12]
  [17 16 15]]

 [[20 19 18]
  [23 22 21]
  [26 25 24]]]
like image 130
Julien Avatar answered Nov 15 '22 12:11

Julien