all of you,
The exact background color is in RGB; (246, 46, 100)
I have tried several methods but those are too slow, one of the methods is below;
new_image = Image.open("image-from-rawpixel-id-6649116-original.png")
img_up = np.asarray(new_image)
for ind1, i in enumerate(tqdm(img_up)):
for ind2, i2 in enumerate(i):
if list(i2[:3]) != a:
img_up2 = img_up.copy()
img_up2.setflags(write=1)
img_up2[ind1][ind2][:3] = [0,0,0]
cv2.imshow('', img_up2)
cv2.waitKey()
I want to make the background white and the foreground person black (masked), but unable to find a quick method.
CodePudding user response:
First you could read image using cv2.imread()
and you get directly numpy.array
.
You can use numpy image[ mask ] = [0,0,0]
to assign value to many pixels in milliseconds.
For exact color you can create mask using img == (100, 46, 247)
.
cv2
keeps image as BGR
instead of RGB
so it needs (100,46,247)
instead of (247,46,100)
.
It needs also .all(axis=-1)
because it compares every value B,G,R
separatelly and gets tuples (True, True, False)
but it needs to reduce it to single True
when all values are True
.
import cv2
img = cv2.imread("image.png")
#print('color:', img[0, 0]) # [100 46 247]
mask = (img == (100, 46, 247)).all(axis=-1)
img1 = img.copy()
img2 = img.copy()
img1[ mask ] = [0,0,0]
img2[ ~mask ] = [0,0,0]
cv2.imshow('image1', img1)
cv2.imshow('image2', img2)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.imwrite('image2-1.png', img1)
cv2.imwrite('image2-2.png', img2)
Result:
image1:
image2:
BTW:
cv2
has function inRange()
to select colors in some ranges and it may give better result.
Example code but I didn't find good range for this image.
import cv2
import numpy as np
img = cv2.imread("image.jpg")
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
#print('hsv:', hsv[0, 0])
lower = np.array([92, 120, 147])
upper = np.array([172, 208, 247]) # for BGR (100, 46, 247) - value from hsv[0,0]
upper = np.array([202, 218, 247])
mask = cv2.inRange(hsv, lower, upper)
print('masking')
# `mask==255` `mask==0`
#img = cv2.bitwise_and(img, img, mask=~mask) # OK
#img[np.where(mask==255)] = [0,0,0] # OK
img[ mask==255 ] = [0,0,0] # OK
#img[ mask.astype(bool) ] = [0,0,0] # OK
#img[ mask ] = [0,0,0] # WRONG (hangs)
print('display')
#h, w = img.shape[:2]
#img = cv2.resize(img, (h//5, w//5))
cv2.imshow('image', img)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.imwrite('image2b.jpg', img)
I actually did that with ImageMagick equivalent operator in Terminal as I don't currently have Python to hand:
magick IXVJl.jpg -fuzz 30% -fill white -draw "color 0,0 floodfill" result.jpg