OpenCV Python - Set background colour

2019-06-28 09:06发布

I am trying to remove a greyish background from a photo and replace it with a white one

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 that the image now has a black background as I have masked out the grey. How can I replace the empty pixels with white ones?

Before After

标签: python opencv
4条回答
一纸荒年 Trace。
2楼-- · 2019-06-28 09:32

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

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

Screenshot

查看更多
再贱就再见
3楼-- · 2019-06-28 09:33

Instead of using bitwise_not, I would use

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

Before doing that I'd also erode and dilate and the mask, to get rid of the specs in the mask that are part of the image you want to keep. http://docs.opencv.org/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html

查看更多
看我几分像从前
4楼-- · 2019-06-28 09:44

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

foreground and background masked then combined

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'),
                   cv2.COLOR_BGR2RGB)
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
查看更多
The star\"
5楼-- · 2019-06-28 09:44

At first, you need to get the background. To this must be subtracted from the original image with the mask image. And then change the black background to white (or any color). And then back to add with the image of the mask. Look here OpenCV grabcut() background color and Contour in Python

查看更多
登录 后发表回答