python OpenCV – add alpha channel to RGB image

Question:

What is the best way to convert RGB image to RGBA in python using opencv?

Let’s say I have one array with shape

(185, 198, 3) - it is RGB

and the other is alpha mask with shape (185, 198)

How to merge them and save to file?

Asked By: Oleg

||

Answers:

You may use cv2.merge() to add the alpha channel to the given RGB image, but first you need to split the RGB image to R, G and B channels, as per the documentation:

Python: cv2.merge(mv[, dst])

  • mv – input array or vector of matrices to be merged; all the matrices in mv must have the same size and the same depth.

And this can be done as:

b_channel, g_channel, r_channel = cv2.split(img)

alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 50 #creating a dummy alpha channel image.

img_BGRA = cv2.merge((b_channel, g_channel, r_channel, alpha_channel))
Answered By: ZdaR

Here is an another simple example using Grabcut, it helps to get the right order of channels when saving the image on disk vs pyplot.

from matplotlib import pyplot as plt
import numpy as np
import cv2

img = cv2.imread('image.jpg')

mask = np.zeros(img.shape[:2], np.uint8)
bgdModel = np.zeros((1,65), np.float64)
fgdModel = np.zeros((1,65), np.float64)
rect = (50, 50, 450, 290)

# Grabcut 
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)

r_channel, g_channel, b_channel = cv2.split(img) 
a_channel = np.where((mask==2)|(mask==0), 0, 255).astype('uint8')  

img_RGBA = cv2.merge((r_channel, g_channel, b_channel, a_channel))
cv2.imwrite("test.png", img_RGBA)

# Now for plot correct colors : 
img_BGRA = cv2.merge((b_channel, g_channel, r_channel, a_channel))

plt.imshow(img_BGRA), plt.colorbar(),plt.show()
Answered By: snoob dogg

With opencv3, this should work:

Python

# First create the image with alpha channel
rgba = cv2.cvtColor(rgb_data, cv2.COLOR_RGB2RGBA)

# Then assign the mask to the last channel of the image
rgba[:, :, 3] = alpha_data

C++

# First create the image with alpha channel
cv::cvtColor(rgb_data, rgba , cv::COLOR_RGB2RGBA);

# Split the image for access to alpha channel
std::vector<cv::Mat>channels(4);
cv::split(rgba, channels);

# Assign the mask to the last channel of the image
channels[3] = alpha_data;

# Finally concat channels for rgba image
cv::merge(channels, 4, rgba);
Answered By: kaanoner

Since OpenCV images are just Numpy arrays, you can do this in one-line, nice and fast with Numpy. So here is the setup code:

import numpy as np

# We'll synthesise a random image and a separate alpha channel full of 128 - semitransparent
im    = np.random.randint(0,256,(480,640,3), dtype=np.uint8)
alpha = np.full((480,640), 128, dtype=np.uint8)

And here is the solution which is simply to stack the alpha channel onto the image in the “depth” axis, hence dstack():

result = np.dstack((im, alpha))
Answered By: Mark Setchell
import cv2
import numpy as np
import skimage.exposure



path_input_image="./input_image.png"


input_image = cv2.imread(path_input_image2, cv2.IMREAD_UNCHANGED)


input_image_alphachann = np.full((input_image.shape[0],input_image.shape[1]), 128, dtype=np.uint8)

output_image = np.dstack((input_image, input_image_alphachann))


print(input_image.shape)
print(output_image.shape)
#(400, 200, 3); 3 channell rgb
#(400, 200, 4); 4c channel rgba



print(input_image.dtype)
print(output_image.dtype)
# uint8




path_output_image=path_input_image+'.alpha.png'
cv2.imwrite(path_output_image, output_image)

Answered By: quine9997

I’ll post here my answer in C++ since it may be helpful to others (there are already enough answers in python):

  std::vector<cv::Mat> matChannels;
  cv::split(mat, matChannels);
  
  // create alpha channel
  cv::Mat alpha(...);
  matChannels.push_back(alpha);

  cv::merge(matChannels, dst);
Answered By: Adriel Jr
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.