【问题标题】:How to do color filtering/masking without HSV color space?如何在没有 HSV 颜色空间的情况下进行颜色过滤/遮罩?
【发布时间】:2019-12-05 21:05:41
【问题描述】:

我和我的团队想知道是否可以仅使用 RGB 值对图像执行颜色过滤。到目前为止,我们只找到了 HSV 的解决方案。我们正在使用 Jupyter Notebook。这是一个可重现的示例:

import cv2
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import hsv_to_rgb


test = cv2.imread('test.jpg')
test = cv2.cvtColor(test, cv2.COLOR_BGR2RGB)
plt.imshow(test) # result below

hsv = cv2.cvtColor(test, cv2.COLOR_RGB2HSV)

lower_orange = np.array([10, 100, 20]) # hsv color space
upper_orange = np.array([25, 255, 255]) # hsv color space
orange_mask = cv2.inRange(hsv, lower_orange, upper_orange)

res = cv2.bitwise_and(test, test, mask = orange_mask)
plt.imshow(res) # result below

所以,上面的代码可以工作,但是我们必须使用 HSV 颜色空间。

这是我在没有 HSV 转换的情况下尝试过的代码(范围值是上面使用的原始橙色 HSV 到 RGB 的直接转换):

lower_orange_rgb = np.array([20, 14, 12]) # rgb color space
upper_orange_rgb = np.array([255, 106, 0]) # rgb color space
orange_mask_rgb = cv2.inRange(test, lower_orange_rgb, upper_orange_rgb)

res = cv2.bitwise_and(test, test, mask = orange_mask_rgb)
plt.imshow(res) # result below

所以,它只是空白,没有用。我们可以仅使用 RGB 颜色空间(不转换为 HSV)执行相同的过滤器/遮罩吗?如果是这样,怎么做?感谢您的任何建议!

【问题讨论】:

  • 我怀疑cv2.inRange 只是对每个通道进行阈值处理。在这方面,在 HSV 中工作要容易得多:您希望 H 有一点变化,而您并不关心 SV。从理论上讲,由于 HSV 是 RGB 的线性变换,因此您也可以在 RGB 中工作,但对于一般颜色,该函数会复杂得多。更不用说,归根结底,该功能类似于 1) 转换为 hsv,2) 对 hsv 进行阈值化;因为这就是颜色过滤的直观含义。
  • 可能直接在 RGB 中执行此操作,但您的动机是什么?如果您认为它会更快,那您可能错了。
  • @MarkRansom 我们不一定希望它更快。对于我们的项目,我们获得了特定的 RGB 范围来创建过滤器。目前,我们将它们转换为 HSV 以进行我们的颜色过滤,但它从来都不是准确的,虽然蒙版会起作用,但它们并没有与我们给出的正确范围完全对齐。我们希望跳过这个过程。
  • @jdizzle 你这样做的方式与你为 HSV 颜色空间所做的完全一样,你只是不转换图像。如果这没有给您想要的结果,那么您需要发布 minimal reproducible example 以便我们可以重现问题。
  • 是 12

标签: python opencv image-processing


【解决方案1】:

当您查看充满活力的图像时,您会看到颜色。 OpenCV 和 Numpy 没有。他们看到了一系列数字。这消除了颜色的所有复杂性。

通过遍历每一行和每一列,很容易找到图像中的所有颜色,然后将像素值保存到一个列表中:

import cv2
import numpy as np   
img = cv2.imread('/home/stephen/Desktop/bIeGp.png')
img = cv2.resize(img, (300,300))
colors = img[100:150,100:250].copy()

# Iterate through each pixel in the colors image
colorsList = []
for x in range(colors.shape[1]):
    for y in range(colors.shape[0]):
        colorsList.append(tuple(colors[y,x]))

上面的代码创建了一个列表,其中包含此图像中颜色的所有像素值:

一旦你知道了这些颜色,你就可以遍历图像中的每个像素,看看颜色是否包含在颜色列表中:

for y in range(img.shape[0]):
    for x in range(img.shape[1]):
        #print(tuple(img[y,x]))
        if colorsList.count(tuple(img[y,x])) > 0:
            img[y,x] = 1,1,1
        else: img[y,x] = 123,123,123
    cv2.imshow('img', img)
    cv2.waitKey(1)

输出:

【讨论】:

    【解决方案2】:

    @Miki 指出了我的愚蠢错误。谢谢你。感谢大家的cmets和帮助。我现在得到了一个很好的面具,虽然它与 HSV 不一样。我必须确保掩码下限的每个 R、G 和 B 值都需要小于掩码上限的相应 R、G 或 B 值。我猜 HSV 到 RGB 的转换并不像看起来那么简单。仍然对此感到困惑,因为我认为这是一个线性转换(不过可能是我使用的在线转换器的错误)。

    【讨论】:

    • 您需要将其视为分别比较图像的每个 R、G、B 通道,而不是单个 r、g、b 颜色。每个通道的下限阈值必须小于上限阈值。
    猜你喜欢
    • 2011-05-25
    • 2011-09-19
    • 1970-01-01
    • 1970-01-01
    • 2013-07-23
    • 2022-11-02
    • 1970-01-01
    • 2011-03-01
    • 2023-03-18
    相关资源
    最近更新 更多