Skip to content Skip to sidebar Skip to footer

Set White Background For A Png Instead Of Transparency With Opencv

I have a OpenCv Image likewise; opencvImage = cv2.cvtColor(numpy_image, cv2.COLOR_RGBA2BGRA) Then with the following code piece, I want to remove the transparency and set a Whit

Solution 1:

Here's a basic script that will replace all fully transparent pixels with white and then remove the alpha channel.

import cv2
#load image with alpha channel.  use IMREAD_UNCHANGED to ensure loading of alpha channel
image = cv2.imread('your image', cv2.IMREAD_UNCHANGED)    

#make mask of where the transparent bits are
trans_mask = image[:,:,3] == 0

#replace areas of transparency with white and not transparent
image[trans_mask] = [255, 255, 255, 255]

#new image without alpha channel...
new_img = cv2.cvtColor(image, cv2.COLOR_BGRA2BGR)

Solution 2:

I do not know exactly what that error is, but I was testing just now a possible solution for you. Even it is in C++, I guess you can convert it easily to python.

/* Setting data info */
std::string test_image_path = "Galicia.png";

/* General variables */
cv::namedWindow("Input image", cv::WINDOW_NORMAL);
cv::namedWindow("Input image R", cv::WINDOW_NORMAL);
cv::namedWindow("Input image G", cv::WINDOW_NORMAL);
cv::namedWindow("Input image B", cv::WINDOW_NORMAL);
cv::namedWindow("Input image A", cv::WINDOW_NORMAL);
cv::namedWindow("Output image", cv::WINDOW_NORMAL);

/* Process */
cv::Mat test_image = cv::imread(test_image_path, cv::IMREAD_UNCHANGED);
std::cout << "Image type: " << test_image.type() << std::endl;

// Split channels of the png files
std::vector<cv::Mat> pngChannels(4);
cv::split(test_image, pngChannels);

cv::imshow("Input image", test_image);
cv::imshow("Input image R", pngChannels[0]);
cv::imshow("Input image G", pngChannels[1]);
cv::imshow("Input image B", pngChannels[2]);
cv::imshow("Input image A", pngChannels[3]);

// Set to255(white) the RGB channels where the Alpha channel(mask) is 0(transparency)
pngChannels[0].setTo(cv::Scalar(255), pngChannels[3]==0);
pngChannels[1].setTo(cv::Scalar(255), pngChannels[3]==0);
pngChannels[2].setTo(cv::Scalar(255), pngChannels[3]==0);

// Merge again the channels
cv::Mat test_image_output;
cv::merge(pngChannels, test_image_output);

// Show the merged channels.
cv::imshow("Output image", test_image_output);

// For saving with changes, conversion is needed.
cv::cvtColor(test_image_output, test_image_output, cv::COLOR_RGBA2RGB);
cv::imwrite("Galicia_mod.png", test_image_output);

I complement the code with this screenshot that may help you to understand better my solution:

enter image description here

Best Wishes, Arritmic

Solution 3:

All previous answers use binarizing but mask can be non binary. In that case you can use alpha blending with white background

defalpha_blend_with_mask(foreground, background, mask): # modified func from link# Convert uint8 to float
    foreground = foreground.astype(float)
    background = background.astype(float)

    # Normalize the mask mask to keep intensity between 0 and 1
    mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
    mask = mask.astype(float) / 255# Multiply the foreground with the mask matte
    foreground = cv2.multiply(mask, foreground)

    # Multiply the background with ( 1 - mask )
    background = cv2.multiply(1.0 - mask, background)

    # Add the masked foreground and background.return cv2.add(foreground, background).astype(np.uint8)

img_with_white_background = alpha_blend_with_mask(img[..., :3], np.ones_like(clip_img) * 255, img[..., 3])

Solution 4:

this worked for me..

# import cv2# #load image with alpha channel.  use IMREAD_UNCHANGED to ensure loading of alpha channel
image = cv2.imread('/content/test1.jpg')    

#make mask of where the transparent bits are
transp_mask = image[:,:,:3] == 0
transp_mask = image[:,:,:3] == 1 # swap #replace areas of transparency with white and not transparent
image[transp_mask] = [100]


#new image without alpha channel...
new_img = cv2.cvtColor(image, cv2.COLOR_BGRA2BGR)
cv2.imwrite('testingnew.jpg',new_img)  converted to binary img
print(new_img.shape)
plt.imshow(new_img)

transparent image

enter image description here

output

enter image description here

output2

enter image description here

real img

enter image description here

Solution 5:

the answer by @user1269942 leave black edges and makes an unnecessary contour around the image. I needed to fill the background to this image This was the image I needed to convert

this is the image after following the steps in accepted answer However If we do masking based on a threshold value we can reduce that unnecessary contour based on how much we choose threshold value. I have choosen 75 in my case. So instead of trans_mask = image[:,:,3] == 0 If we do

img2gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)    
ret, trans_mask = cv2.threshold(img2gray, 75, 255, cv2.THRESH_BINARY)    
trans_mask = trans_mask == 0deffillColor(imageFile, color):    
  image = cv2.imread(imageFile, cv2.IMREAD_UNCHANGED)    
  #trans_mask = image[:,:,3] == 0
  img2gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)    
  ret, trans_mask = cv2.threshold(img2gray, 75, 255, cv2.THRESH_BINARY)
  trans_mask = trans_mask == 0
  image[trans_mask] = color    
  new_img = cv2.cvtColor(image, cv2.COLOR_BGRA2BGR)    
  return new_img

The Output Image

Post a Comment for "Set White Background For A Png Instead Of Transparency With Opencv"