Numpy where() 创建与定义颜色不同的点
Numpy where() creates spots of different color than the ones defined
我正在编写一个为图像创建遮罩的脚本。我的输入图像如下所示:
原图只有40x40px,仅供参考:
我想为图像中心的紫色区域创建一个遮罩。这就是我所做的:
# 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 notebook 中复制
主要问题是您尝试比较三个通道,但只为一个通道设置值。这很可能导致面罩上出现蓝色区域。当您使用 np.where()
将其他像素设置为黑色时,您只是在第一个通道而不是所有三个通道上设置它。您可以通过拆分每个通道并打印 before/after 数组来可视化这一点,这将向您显示生成的数组值为 RGB(0,0,255)
。因此,为了解决这个问题,我们需要比较每个单独的通道,然后将所需区域设置为白色,同时将所有三个通道的蒙版上的任何黑色区域设置为黑色。这是一种方法:
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 通道),然后将所有非白色像素更改为黑色。
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: 灰度工作 space
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 颜色 space 然后使用较低和较高的颜色范围来分割图像以创建二进制掩码
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()
两种方法应该产生相同的结果
如果你有一个 3 通道图像(即 RGB 或 BGR 或类似的)并且你想为每个像素生成一个通道掩码(即你想要 0/1 或 True/False),那么你实际上需要使用 np.all()
将 3 个值组合成一个值,如下所示:
import cv2
import numpy as np
# Load image and get centre colour
image = cv2.imread('40x40.png')
cc = im[20, 20]
print(image.shape)
(40, 40, 3)
# Generate list of unique colours present in image so we know what we are dealing with
print(np.unique(im.reshape(-1,3), axis=0))
array([[140, 109, 142],
[151, 106, 140],
[160, 101, 137],
[165, 134, 157],
[175, 149, 171],
[206, 87, 109],
[206, 185, 193]], dtype=uint8)
# Generate mask of pixels matching centre colour
mask_bw = np.where(np.all(im==cc,axis=2), 255, 0)
# Check shape of mask - no 3rd dimension !!!
print(mask_bw.shape)
(40, 40)
# Check unique colours in mask
print(np.unique(mask_bw.reshape(-1,1), axis=0))
array([[ 0],
[255]])
我正在编写一个为图像创建遮罩的脚本。我的输入图像如下所示:
原图只有40x40px,仅供参考:
我想为图像中心的紫色区域创建一个遮罩。这就是我所做的:
# 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 notebook 中复制
主要问题是您尝试比较三个通道,但只为一个通道设置值。这很可能导致面罩上出现蓝色区域。当您使用 np.where()
将其他像素设置为黑色时,您只是在第一个通道而不是所有三个通道上设置它。您可以通过拆分每个通道并打印 before/after 数组来可视化这一点,这将向您显示生成的数组值为 RGB(0,0,255)
。因此,为了解决这个问题,我们需要比较每个单独的通道,然后将所需区域设置为白色,同时将所有三个通道的蒙版上的任何黑色区域设置为黑色。这是一种方法:
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 通道),然后将所有非白色像素更改为黑色。
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: 灰度工作 space
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 颜色 space 然后使用较低和较高的颜色范围来分割图像以创建二进制掩码
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()
两种方法应该产生相同的结果
如果你有一个 3 通道图像(即 RGB 或 BGR 或类似的)并且你想为每个像素生成一个通道掩码(即你想要 0/1 或 True/False),那么你实际上需要使用 np.all()
将 3 个值组合成一个值,如下所示:
import cv2
import numpy as np
# Load image and get centre colour
image = cv2.imread('40x40.png')
cc = im[20, 20]
print(image.shape)
(40, 40, 3)
# Generate list of unique colours present in image so we know what we are dealing with
print(np.unique(im.reshape(-1,3), axis=0))
array([[140, 109, 142],
[151, 106, 140],
[160, 101, 137],
[165, 134, 157],
[175, 149, 171],
[206, 87, 109],
[206, 185, 193]], dtype=uint8)
# Generate mask of pixels matching centre colour
mask_bw = np.where(np.all(im==cc,axis=2), 255, 0)
# Check shape of mask - no 3rd dimension !!!
print(mask_bw.shape)
(40, 40)
# Check unique colours in mask
print(np.unique(mask_bw.reshape(-1,1), axis=0))
array([[ 0],
[255]])