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))
添加回答
舉報