opencv 如果我知道RGB背景的颜色范围,谁能告诉我如何改变前景的遮罩?

6gpjuf90  于 2022-11-15  发布在  其他
关注(0)|答案(2)|浏览(201)

你们所有人,

**这是图像;**x1c 0d1x的
准确的背景颜色为RGB;(246、46、100)

我试过几种方法,但都太慢了,下面是其中一种方法;

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()

我想把背景变成白色,把前景人物变成黑色(蒙面),但是找不到一个快捷的方法。

已修改

我已经绑定了另一个方法来屏蔽前景,但我认为,我做了一些错误,而转换之间的RGB。

path = 'image-from-rawpixel-id-2923073-png.png'

im = Image.open(path).convert('RGBA')

img = cv2.imread(path, cv2.IMREAD_UNCHANGED)

#--------------------------- To change the background color that is not present in the foreground ---------------------------------------------
lst_ch_a = []
for pixel in tqdm(im.getdata()):
    lst_ch_a.append(pixel[:3])

break_out = True
while break_out:
    a = random.sample(range(0, 255), 3)
    if a not in lst_ch_a:
        new_image = Image.new("RGBA", im.size, tuple(a))
        print(tuple(a))
        break_out = False

new_image.paste(im, mask=im)
new_image.convert("RGB").save("check6.jpg")

#--------------------------- Numpy ----------------------------------------------------------------
img_up = np.asarray(new_image)

img = img_up.copy()
img.setflags(write=1)
img[:,:,:3][img[:,:,:3] != tuple(a)] = 0
img[img!=0]=255

img = cv2.cvtColor(img, cv2.COLOR_BGRA2RGBA)
img = cv2.resize(img,(500,500), cv2.INTER_LINEAR)

cv2.imwrite('results1.jpg', img)

cv2.imshow('', img)
cv2.waitKey(0)

下面是结果,但我得到的像素蓝色,绿色,红色,和一些其他颜色的图像。你知道为什么我得到这个吗?

你可以看到在上面的第一个图像,我已经改变了背景。图像是透明的图像,但后来我改变了背景颜色。没有绿色,蓝色,或红色,但当掩盖前景的红色,蓝色,绿色出现。
你知道为什么会这样吗?

qnyhuwrf

qnyhuwrf1#

首先,你可以用cv2.imread()来读取图像,你直接得到numpy.array
您可以使用numpy image[ mask ] = [0,0,0]以毫秒为单位为多个像素赋值。
对于精确的颜色,您可以使用img == (100, 46, 247)创建遮罩。
cv2将映像保留为BGR而不是RGB,因此它需要(100,46,247)而不是(247,46,100)
它还需要.all(axis=-1),因为它分别比较每个值B,G,R,并获得元组(True, True, False),但当所有值都是True时,它需要将其减少为单个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)

结果:
图像1:

图2:

顺便说一句:

cv2具有inRange()功能,用于在某些范围内选择颜色,并且可能给予更好的结果。
示例代码,但我没有找到这个图像的好范围。
除此之外,它开始删除嘴唇中的相似像素。

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)

另请参阅:Finding red color in image using Python & OpenCV - Stack Overflow

gopyfrb3

gopyfrb32#

您应该能够使用此处描述的PIL.ImageDraw.floodfill()更有效地执行此操作。
如果使用全局替换,您将在图像中出现的任何地方捕捉到微红色调(如模特的嘴唇)。如果使用具有适当容差的左上角泛色填充,则泛色应该在污染嘴唇之前被她的黑发阻挡。
结果应该是这样的:

实际上,我在终端中使用了ImageMagick等效操作符,因为我目前手头没有Python:

magick IXVJl.jpg -fuzz 30% -fill white -draw "color 0,0 floodfill" result.jpg

相关问题