python - Numpy where() 创建与定义颜色不同的点

标签 python numpy image-processing image-segmentation

我正在编写一个为图像创建蒙版的脚本。我的输入图像如下所示:

input image

原图只有40x40px,仅供引用:enter image description here

我想创建图像中心紫色区域的 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 with blue areas

这已经够奇怪的了,但是如果我尝试删除蓝色区域,这也不起作用。

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 上的任何黑色区域设置为黑色。这是一种方法:

enter image description here

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/

相关文章:

python - 如何在python中读取bmp文件头?

python - 通过套接字发送和接收数组

python - 将元组列表转换为切片列表以与 np.r_ 一起使用

python - pandas - 转换数据 View

c++ - 如何在 OpenCV 中获取特定元素的行和列?

matlab - 如何使用矩阵作为输入来训练 Matlab 神经网络?

python pandas - 根据另一列的内容将列中的值更改为 bool 值

python - 使用python中的struct模块打包和解包可变长度数组/字符串

python - 何时以及如何在 python 中使用内置函数 property()

python - numpy.arange 返回数组的多个副本?