<p>不幸的是,没有快速的方法可以做到这一点。无论您使用循环还是优化的numpy解决方案,在引擎盖下,您都必须根据<code>rgbL</code>的每个元素检查每个像素。考虑到所有这些,您可以使用<a href="https://numpy.org/doc/stable/reference/generated/numpy.isin.html" rel="nofollow noreferrer">^{<cd2>}</a>与数据的<a href="https://numpy.org/doc/stable/user/basics.rec.html" rel="nofollow noreferrer">structured array</a><a href="https://numpy.org/doc/stable/reference/generated/numpy.ndarray.view.html" rel="nofollow noreferrer">^{<cd3>}</a>组合来执行正确的分组</p>
<p>诀窍是制作一个表示像素的<a href="https://numpy.org/devdocs/reference/arrays.dtypes.html" rel="nofollow noreferrer">custom type</a>。这样,您可以比较整个元素,而不是颜色通道,这是默认情况下<code>isin</code>所做的</p>
<pre><code>pixel = np.dtype([('r', img.dtype), ('g', img.dtype), ('b', img.dtype)])
</code></pre>
<p>不能将像素数据类型定义为这样的子数组类型<code>pixel = np.dtype((img.dtype, img.shape[-1]))</code>。这将在您尝试查看数据时导致错误</p>
<p>现在,您可以将<code>img</code>视为<code>pixel</code>元素的2D数组,而不是<code>uint8</code>或<code>float</code>的3D数组,具体视情况而定:</p>
<pre><code>data = img.view(pixel).squeeze(axis=-1)
</code></pre>
<p>您可以对列表执行相同的操作:</p>
<pre><code>rgbA = np.array(rgbL).view(pixel).squeeze(axis=-1)
</code></pre>
<p>你也可以</p>
<pre><code>rgbA = np.array([tuple(p) for p in rgbL], dtype=pixel)
</code></pre>
<p>您不能使用<code>np.array(rgbL, dtype=pixel)</code>,因为在这种情况下,元素将无法正确初始化</p>
<p>现在<code>isin</code>将为您提供所需的掩码:</p>
<pre><code>mask = np.isin(data, rgbA)
</code></pre>
<p>您可以直接应用遮罩:</p>
<pre><code>data[mask] = 255
</code></pre>
<p>如果要设置通道之间不同的值,请记住使用元组指定像素条目:</p>
<pre><code>>>> 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
</code></pre>
<p>因为<code>data</code>是对<code>img</code>的一个视图,所以就完成了</p>
<p><strong>注意:</strong>仅当图像在三维中连续时,此操作才有效。否则,您将无法对两个阵列使用相同的数据类型。如果不是这样,则必须复制图像数据,使其至少在第三维中是连续的。对于大多数正常的阵列来说,它们不是超光谱图像或其他东西上的奇怪视图,你会没事的</p>
<p><strong>TL;DR</strong></p>
<pre><code>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)
</code></pre>