如何输出只包含特定颜色范围的图像?

How to ouput image containing only specified color range?

我只想要输出图像中的紫色车道。

import cv2
import numpy as np

img = cv2.imread("minimap_example.png")
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) #hsv image

lower_purple = np.array([154,135,160])
upper_purple = np.array([167,90,235])

mask = cv2.inRange(hsv, lower_purple, upper_purple)

lane = cv2.bitwise_and(img, img, mask=mask)
cv2.imwrite("laneOnly.png", lane)

但是输出的图像根本不正确:

如何解决这个错误?

范围有问题。

如果您检查(打印)您的图像,放大到此切片 hsv[40:60, 80:90] 的车道,您会发现 hsv 颜色的值在 [136 167 243] 左右。

所以尝试使用这些值会得到更好的结果:

lower_purple = (136,167,155)
upper_purple = (136,167,243)

所以,深入挖掘并为您找到更好的选择。

尝试:

%%capture
%matplotlib inline
from skimage import io
from ipywidgets import interact, widgets
from IPython.display import display
import cv2
from scipy import misc
import matplotlib.pyplot as plt
import numpy as np

def f(lower_H, lower_S, lower_V, upper_H, upper_S, upper_V, **kwargs):
    hsv = cv2.cvtColor(racoon, cv2.COLOR_BGR2HSV)

    lower_range = np.array([lower_H, lower_S, lower_V])
    upper_range = np.array([upper_H, upper_S, upper_V])

    mask = cv2.inRange(hsv, lower_range, upper_range)

    ax_neu.imshow(mask, cmap="gray")
    ax_neu.set_title(f"Lower Range: H = {lower_H}, S = {lower_S}, V = {lower_V}\
                     \nUpper Range: H = {upper_H}, S = {upper_S}, V = {upper_V}")
    fig.canvas.draw()
    display(fig)

    

img = io.imread('https://i.stack.imgur.com/6UnnM.png/')
# racoon = cv2.imread('')
print(img.shape)

fig = plt.figure(figsize=(10, 8))
ax_orig = fig.add_subplot(121) 
ax_neu = fig.add_subplot(122) 

ax_orig.imshow(img, cmap="gray")
ax_neu.imshow(img, cmap="gray")

print("Setting Lower and Upper Range for HSV")
interact(f, lower_H=widgets.IntSlider(min=1,max=255,step=1,value=105),
            lower_S=widgets.IntSlider(min=1,max=255,step=1,value=130),
            lower_V=widgets.IntSlider(min=1,max=255,step=1,value=110),
            upper_H=widgets.IntSlider(min=1,max=255,step=1,value=225),
            upper_S=widgets.IntSlider(min=1,max=255,step=1,value=205),
            upper_V=widgets.IntSlider(min=1,max=255,step=1,value=255))

结果为:

lower_purple = (105, 130, 110)
upper_purple = (225, 205, 255)

你做错了两件事:

  • 您正在使用 RGB ranges/values 但您正在将图像转换为 HSV。为简单起见,将其保留为 RGB(即使 HSV 是正确的方式)。
  • 您正在按 RGB 顺序表示它们,但图像是 BGR,因此请调换值的顺序。而且把范围扩大一点...否则什么也得不到

我建议你这样做:

import cv2

img = cv2.imread("minimap_example.png")

lower_purple = (100, 45, 120) # you might want to refine these
upper_purple = (260, 105, 200) # you might want to refine these

mask = cv2.inRange(img, lower_purple, upper_purple)

lane = cv2.bitwise_and(img, img, mask=mask)
cv2.imwrite("laneOnly.png", lane)

你会得到这个输出: