![](/img/trans.png)
[英]How to replace all RGB values in an Numpy Image Arrray based on an Target Pixel
[英]How to replace all RGB values in an image if that RGB value belongs to a list
如果 RGB 值在我的列表中沒有循環,我需要更改圖像中的所有 RGB 值。
我知道為了更改 RGB 值我只需要這樣做:
img[np.all(img == (99, 121, 109), axis=-1)] = (255,255,255)
但是我的值(99, 121, 109)
屬於一個列表,例如
rgbL = [[99, 121, 109],
[102, 118, 107],
[102, 126, 114],
.......,
[105, 114, 101]]
為了更改屬於我的rgbL
列表的圖像中的所有 RGB 值,我需要循環到我的rgbL
的所有值。 但是我的清單太長了。 有沒有辦法不用循環就可以做到這一點?
不幸的是,沒有快速的方法可以做到這一點。 無論您使用循環還是優化的 numpy 解決方案,在幕后您都必須針對rgbL
的每個元素檢查每個像素。 考慮到所有這些,您可以使用isin
結合數據的結構化數組view
來執行正確的分組。
訣竅是創建一個表示像素的自定義類型。 這樣,您就可以比較整個元素而不是顏色通道,這是默認情況下isin
所做的。
pixel = np.dtype([('r', img.dtype), ('g', img.dtype), ('b', img.dtype)])
您不能將像素數據類型定義為像這樣的子數組類型pixel = np.dtype((img.dtype, img.shape[-1]))
。 當您嘗試查看數據時,這將導致錯誤。
您現在可以將img
視為pixel
元素的二維數組,而不是 3D 數組uint8
或float
,視情況而定:
data = img.view(pixel).squeeze(axis=-1)
您可以對列表執行相同的操作:
rgbA = np.array(rgbL).view(pixel).squeeze(axis=-1)
你也可以做
rgbA = np.array([tuple(p) for p in rgbL], dtype=pixel)
您不能使用np.array(rgbL, dtype=pixel)
因為在這種情況下元素不會被正確初始化。
現在isin
會給你你想要的面具:
mask = np.isin(data, rgbA)
您可以直接敷面膜:
data[mask] = 255
如果要設置不同通道的值,請記住使用元組來指定像素條目:
>>> data[mask] = (255, 255, 255) # OK
>>> data[mask] = [255, 255, 255]
ValueError: NumPy boolean array indexing assignment cannot assign 3 input values to the 1 output values where the mask is true
由於data
是img
的視圖,因此您已完成。
注意:這僅在您的圖像在三維空間中是連續的時才有效。 否則,您將無法對兩個 arrays 使用相同的數據類型。如果不是這種情況,您將必須復制圖像數據,使其至少在三維上是連續的。 對於大多數理智的 arrays 不是高光譜圖像或其他東西的奇怪視圖,你會沒事的。
長話短說
pixel = np.dtype([('r', img.dtype), ('g', img.dtype), ('b', img.dtype)])
def replace(img, pixels, value):
data = img.view(pixel).squeeze(-1)
pixels = np.array(pixels, dtype=img.dtype).view(pixel).squeeze(-1)
data[isin(data, pixels)] = tuple(value)
如果這適用於單一顏色:
img[np.all(img == (99, 121, 109), axis=-1)] = (255,255,255)
這應該適用於列表:
img[np.all(img in rgbL, axis=-1)] = (255,255,255)
使用 cv2 LUT(查找表)——您可以定義自己的 LUT 並直接指定您的替換項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.