1 回答
TA贡献1785条经验 获得超8个赞
更新
现在,您的实际预期处理已经变得更加清晰,OpenCV功能可能会更好地为您服务。喜欢这个:inRange()
#!/usr/local/bin/python3
import cv2 as cv
import numpy as np
# Load the image and convert to HLS
image = cv.imread("image.jpg")
hls = cv.cvtColor(image,cv.COLOR_BGR2HLS)
# Define lower and uppper limits for each component
lo = np.array([50,0,0])
hi = np.array([70,255,255])
# Mask image to only select filtered pixels
mask = cv.inRange(hls,lo,hi)
# Change image to white where we found our colour
image[mask>0]=(255,255,255)
cv.imwrite("result.png",image)
因此,如果我们使用此图像:
我们选择 50-70 范围内的色调,并将它们设置为白色:
如果你去这里一个颜色转换器,你可以看到“绿色”是Hue=120,但是OpenCV将Hue除以2,这样360度就变成了180,并且仍然适合uint8。因此,我们在代码中的60表示在线颜色转换器中的120。
OpenCV用于uint8图像的范围是:
色相 0..180
亮度 0..255
饱和度 0..255
正如我之前所说,您应该养成在调试器中查看数据类型,形状和范围的习惯。要查看 、和最大色相、亮度和饱和度,请使用:shape
dtype
print(hls.dtype, hls.shape)
print(hls[...,0].max())
print(hls[...,1].max())
print(hls[...,2].max())
原始答案
有几种方法可以做到这一点。性能最高的可能是OpenCV函数,StackOverflow上有很多关于此的答案。cv2.inRange()
这是一个Numpy的方式。如果您阅读注释并查看打印的值,则可以了解如何将逻辑 AND 与逻辑 OR 等组合在一起,以及如何解决特定通道问题。
#!/usr/bin/env python3
from random import randint, seed
import numpy as np
# Generate a repeatable random HSV image
np.random.seed(42)
h, w = 4, 5
HSV = np.random.randint(1,100,(h,w,3),dtype=np.uint8)
print('Initial HSV\n',HSV)
# Create mask of all pixels with acceptable Hue, i.e. H > 50
HueOK = HSV[...,0] > 50
print('HueOK\n',HueOK)
# Create mask of all pixels with acceptable Saturation, i.e. S > 20 AND S < 80
SatOK = np.logical_and(HSV[...,1]>20, HSV[...,1]<80)
print('SatOK\n',SatOK)
# Create mask of all pixels with acceptable value, i.e. V < 20 OR V > 60
ValOK = np.logical_or(HSV[...,2]<20, HSV[...,2]>60)
print('ValOK\n',ValOK)
# Combine masks
combinedMask = HueOK & SatOK & ValOK
print('Combined\n',combinedMask)
# Now, if you just want to set the masked pixels to 255
HSV[combinedMask] = 255
print('Result1\n',HSV)
# Or, if you want to set the masked pixels to one value and the others to another value
HSV = np.where(combinedMask,255,0)
print('Result2\n',HSV)
示例输出
Initial HSV
[[[93 98 96]
[52 62 76]
[93 4 99]
[15 22 47]
[60 72 85]]
[[26 72 61]
[47 66 26]
[21 45 76]
[25 87 40]
[25 35 83]]
[[66 40 87]
[24 26 75]
[18 95 15]
[75 86 18]
[88 57 62]]
[[94 86 45]
[99 26 19]
[37 24 63]
[69 54 3]
[33 33 39]]]
HueOK
[[ True True True False True]
[False False False False False]
[ True False False True True]
[ True True False True False]]
SatOK
[[False True False True True]
[ True True True False True]
[ True True False False True]
[False True True True True]]
ValOK
[[ True True True False True]
[ True False True False True]
[ True True True True True]
[False True True True False]]
Combined
[[False True False False True]
[False False False False False]
[ True False False False True]
[False True False True False]]
Result1
[[[ 93 98 96]
[255 255 255]
[ 93 4 99]
[ 15 22 47]
[255 255 255]]
[[ 26 72 61]
[ 47 66 26]
[ 21 45 76]
[ 25 87 40]
[ 25 35 83]]
[[255 255 255]
[ 24 26 75]
[ 18 95 15]
[ 75 86 18]
[255 255 255]]
[[ 94 86 45]
[255 255 255]
[ 37 24 63]
[255 255 255]
[ 33 33 39]]]
Result2
[[ 0 255 0 0 255]
[ 0 0 0 0 0]
[255 0 0 0 255]
[ 0 255 0 255 0]]
备注:
1) 您还可以使用否定访问蒙版未选择的像素:
# All unmasked pixels become 3
HSV[~combinedMask] = 3
2)省略号()只是一个快捷方式,意思是“我没有打扰列出的所有其他维度”,所以与...HSV[...,1]HSV[:,:,1]
3)如果您不喜欢为Hue和饱和度写作,则可以拆分通道HSV[...,0]HSV[...,1]
H, S, V = cv2.split(HSV)
然后,您可以使用 代替 .完成后,如果要将通道重新组合回 3 通道映像,可以执行以下操作:HHSV[...,0]
HSV = cv2.merge((H,S,V))
或
HSV = np.dstack((H,S,V))
添加回答
举报