0

我们想对 RGB 图像应用颜色阈值:

原始图像

当我们指定下限为[0, 0, 0],上限为时,[255, 255, 255]结果如下:

掩码为 0

并且,当下限为[1, 1, 1]上限时[255, 255, 255],结果如下:

带 1 的面具

为什么一个像素的差异会在遮蔽上造成如此剧烈的变化?

代码:

lower_blue = np.array([0,0,0]) 
upper_blue = np.array([255,255,255])
mask = cv2.inRange(image_copy, lower_blue, upper_blue)
plt.imshow(mask,cmap='gray')
4

1 回答 1

2

您的主要“问题”是 Matplotlib 的imshow功能。

在您的第一种情况下,您只需屏蔽图像中的所有像素,以便所有像素mask都具有 value 255。当imshow在此类图像上不使用任何参数时,将应用自动颜色缩放,以便0为所有像素设置相应的绘图,因为所有像素都具有相同的值。如果您在调用中明确设置vminvmax(请参阅链接的文档页面)imshow,您会看到预期的全白图。

第二种情况的微小变化会导致某些像素mask0,因此即使是标准imshow调用也会产生“正确”的颜色缩放,因为像素mask覆盖了整个“范围” [0 ... 255],因为只有0和的像素值255

现在,要检测蓝色背景:在您的情况下,蓝色背景似乎具有固定的 RGB 值,因此将 OpenCVinRange与标准 BGR 图像一起使用可能是合适的。一般来说,对于颜色遮罩,将图像转换为 HSV/HSL 颜色空间更为复杂 - 从我的角度来看。H有关选择正确的, S,值的简短介绍,L请参阅我在较早的问题上所做的这个答案。

我为上述比较以及实际检测蓝色背景做了一些代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt

image = cv2.imread('8au0O.jpg')

lower_blue = np.array([0, 0, 0])
upper_blue = np.array([255, 255, 255])
mask_lb000 = cv2.inRange(image, lower_blue, upper_blue)

plt.figure()
plt.subplot(2, 3, 1)
plt.imshow(mask_lb000, cmap='gray')
plt.title('imshow without explicit vmin, vmax')
plt.subplot(2, 3, 4)
plt.imshow(mask_lb000, cmap='gray', vmin=0, vmax=255)
plt.title('imshow with explicit vmin, vmax')

lower_blue = np.array([1, 1, 1])
upper_blue = np.array([255, 255, 255])
mask_lb111 = cv2.inRange(image, lower_blue, upper_blue)

plt.subplot(2, 3, 2)
plt.imshow(mask_lb111, cmap='gray')
plt.title('imshow without explicit vmin, vmax')
plt.subplot(2, 3, 5)
plt.imshow(mask_lb111, cmap='gray', vmin=0, vmax=255)
plt.title('imshow with explicit vmin, vmax')

# Detect blue-ish areas in HSL converted image
# H value must be appropriate (see HSL color space), e.g. within [200 ... 260]
# L value can be arbitrary (we want everything between bright and dark blue), e.g. within [0.0 ... 1.0]
# S value must be above some threshold (we want at least some saturation), e.g. within [0.35 ... 1.0]
lower_blue = np.array([np.round(200 / 2), np.round(0.00 * 255), np.round(0.35 * 255)])
upper_blue = np.array([np.round(260 / 2), np.round(1.00 * 255), np.round(1.00 * 255)])
mask_lb = cv2.inRange(cv2.cvtColor(image, cv2.COLOR_BGR2HSV), lower_blue, upper_blue)

plt.subplot(2, 3, 3)
plt.imshow(mask_lb, cmap='gray')
plt.title('imshow without explicit vmin, vmax')
plt.subplot(2, 3, 6)
plt.imshow(mask_lb, cmap='gray', vmin=0, vmax=255)
plt.title('imshow with explicit vmin, vmax')

plt.show()

这是生成的输出:

输出

希望有帮助!

于 2019-10-25T05:54:25.973 回答