我正在编写一个为图像创建蒙版的脚本。我的输入图像如下所示:
我想创建图像中心紫色区域的 mask 。这就是我所做的:
# read the 40x40 image and convert it to RGB
input_image = cv2.cvtColor(cv2.imread('image.png'), cv2.COLOR_BGR2RGB)
# get the value of the color in the center of the image
center_color = input_image[20, 20]
# create the mask: pixels with same color = 255 (white), other pixels = 0 (black)
mask_bw = np.where(input_image == center_color, 255, 0)
# show the image
plt.imshow(mask_bw)
大多数时候,这工作得很好,但对于某些图像(比如我附加到这个问题的图像),我的蒙版中总是出现一些蓝色区域,如下图所示。这是可重现的,并且对于相同的输入图像,区域始终相同。
这已经够奇怪的了,但是如果我尝试删除蓝色区域,这也不起作用。
mask_bw[mask_bw != (255, 255, 255)] = 0 # this doesn't change anything..
为什么会发生这种情况以及如何解决这个问题?
其他信息
- 尝试使用 numpy 版本 1.17.3 和 1.17.4
- 在我的本地环境和 Google Colab 笔记本中复制
最佳答案
主要问题是您尝试比较三个 channel ,但只设置一个 channel 的值。这很可能是导致 mask 上出现蓝色区域的原因。当您使用 np.where() 将其他像素设置为黑色时,您仅在第一个 channel 而不是所有三个 channel 上进行设置。您可以通过分割每个 channel 并打印之前/之后的数组来可视化这一点,这将显示结果数组值为 RGB(0,0,255)
。因此,为了解决这个问题,我们需要比较每个单独的 channel ,然后将所需区域设置为白色,同时将所有三个 channel 的 mask 上的任何黑色区域设置为黑色。这是一种方法:
import numpy as np
import cv2
image = cv2.imread('1.png')
center_color = image[20, 20]
b, g, r = cv2.split(image)
mask = (b == center_color[0]) & (g == center_color[1]) & (r == center_color[2])
image[mask] = 255
image[mask==0] = 0
cv2.imshow('image', image)
cv2.waitKey()
使用当前代码删除蓝色区域的修补程序是将图像转换为灰度(1 channel ),然后将所有非白色像素更改为黑色。
import numpy as np
import cv2
# Load image, find color, create mask
image = cv2.imread('1.png')
center_color = image[20, 20]
mask = np.where(image == center_color, 255, 0)
mask = np.array(mask, dtype=np.uint8)
# Convert image to grayscale, convert all non-white pixels to black
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
mask[mask != 255] = 0
cv2.imshow('mask', mask)
cv2.waitKey()
<小时/>
这里有两种获取紫色区域蒙版的替代方法
方法#1:在灰度空间中工作
import numpy as np
import cv2
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
center_color = gray[20, 20]
mask = np.array(np.where(gray == center_color, 255, 0), dtype=np.uint8)
cv2.imshow('mask', mask)
cv2.waitKey()
方法#2:颜色阈值
这个想法是将图像转换为 HSV 颜色空间,然后使用较低和较高的颜色范围来分割图像以创建二进制蒙版
import numpy as np
import cv2
image = cv2.imread('1.png')
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([0, 124, 0])
upper = np.array([179, 255, 255])
mask = cv2.inRange(hsv, lower, upper)
cv2.imshow('mask', mask)
cv2.waitKey()
两种方法应该产生相同的结果
关于python - Numpy where() 创建与定义颜色不同的点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58862573/