'python OpenCV - add alpha channel to RGB image
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?
Solution 1:[1]
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))
Solution 2:[2]
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);
Solution 3:[3]
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))
Solution 4:[4]
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()
Solution 5:[5]
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)
Solution 6:[6]
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);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | Mark Setchell |
Solution 4 | snoob dogg |
Solution 5 | quine9997 |
Solution 6 | Adriel Jr |