python OpenCV - add alpha channel to RGB image

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

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

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

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

Tags:

Python

Opencv