OpenCV Python - set background color

I am trying to remove the grayish background from a photo and replace it with white

So far I have this code:

image = cv2.imread(args["image"])
r = 150.0 / image.shape[1]
dim = (150, int(image.shape[0] * r))
resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
lower_white = np.array([220, 220, 220], dtype=np.uint8)
upper_white = np.array([255, 255, 255], dtype=np.uint8)
mask = cv2.inRange(resized, lower_white, upper_white) # could also use threshold
res = cv2.bitwise_not(resized, resized, mask)
cv2.imshow('res', res) # gives black background


The problem is the image now has a black background as I masked out the gray. How to replace empty pixels with white ones?



source to share

4 answers

You can use a mask to index the array and assign the white parts of the mask to white:

coloured = resized.copy()
coloured[mask == 255] = (255, 255, 255)





I really recommend you stick with OpenCV, it is well optimized. The trick is to invert the mask and apply it to some background, you will have a masked image and a masked background, then you combine both. image1 is your image masked by the original mask, image2 is the background image masked by the inverted mask, and image3 is the combined image. Important. image1, image2 and image3 must be the same size and type. The mask should be in grayscale.

foreground and background are masked and then merged

import cv2
import numpy as np

# opencv loads the image in BGR, convert it to RGB
img = cv2.cvtColor(cv2.imread('E:\\FOTOS\\opencv\\zAJLd.jpg'),
lower_white = np.array([220, 220, 220], dtype=np.uint8)
upper_white = np.array([255, 255, 255], dtype=np.uint8)
mask = cv2.inRange(img, lower_white, upper_white)  # could also use threshold
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)))  # "erase" the small white points in the resulting mask
mask = cv2.bitwise_not(mask)  # invert mask

# load background (could be an image too)
bk = np.full(img.shape, 255, dtype=np.uint8)  # white bk

# get masked foreground
fg_masked = cv2.bitwise_and(img, img, mask=mask)

# get masked background, mask must be inverted 
mask = cv2.bitwise_not(mask)
bk_masked = cv2.bitwise_and(bk, bk, mask=mask)

# combine masked foreground and masked background 
final = cv2.bitwise_or(fg_masked, bk_masked)
mask = cv2.bitwise_not(mask)  # revert mask to original




First you need to get the background. To this you need to subtract from the original image with the mask image. And then change the black background to white (or any color). And then add the mask image again. Look here OpenCV grabcut () background color and outline in Python



Instead of using bitwise_not, I would use

resized.setTo([255, 255, 255], mask)


Before doing this, I also blur and expand the mask to get rid of the specs in the mask that are part of the image you want to keep.



All Articles