【问题标题】:Using array mask to change pixels values使用数组掩码更改像素值
【发布时间】:2015-04-20 03:26:23
【问题描述】:

说明

我有一张图片和它的面具。我正在使用 PIL 和 Numpy 应用以下规则:

  • 掩码为红色(255, 0, 0) 的像素设置为(0, 0, 0)
  • 掩码为绿色的像素(0, 255, 0),设置为(64, 64, 64)
  • 蒙版为蓝色的像素(0, 0, 255),设置为(128, 128, 128)
  • 蒙版为黄色的像素(255, 255, 0),设置为(255, 255, 255)
  • 否则,保持像素不变。

我尝试过的

利用数组掩码的思想,我尝试了以下方法:

import numpy as np
import Image

# (R G B)
red = [255, 0, 0]
green = [0, 255, 0]
blue = [0, 0, 255]
yellow = [255, 255, 0]


def execute():
    im = Image.open('input.png')
    data = np.array(im)
    print "Original = ", data.shape

    mask = Image.open('mask2.png')
    data_mask = np.array(mask)
    print "Mask = ", data_mask.shape

    red_mask = data_mask == red
    green_mask = data_mask == green
    blue_mask = data_mask == blue
    yellow_mask = data_mask == yellow

    data[red_mask] = [0, 0, 0]
    data[green_mask] = [64, 64, 64]
    data[blue_mask] = [128, 128, 128]
    data[yellow_mask] = [255, 255, 255]

    im = Image.fromarray(data)
    im.save('output.png')


if __name__ == "__main__":
    execute()

问题

上面的代码输出:

Original =  (64, 64, 3)
Mask =  (64, 64, 3)
ValueError: NumPy boolean array indexing assignment cannot assign 3 input values to the 5012 output values where the mask is true

我错过了什么吗?如何使用数组掩码的思想来改变像素值?

【问题讨论】:

  • 这不是你的问题,但如果你使用的是import Image 而不是from PIL import Image,这意味着你使用的是 PIL 而不是它的现代 fork Pillow。除非你真的需要与非常旧版本的 Python 向后兼容,或者由于某种原因不能与 Pillow 一起使用的代码(不应该有这样的东西,但总会有错误,对吧?),不要这样做那个。
  • 供将来参考:PIL 的东西在这里根本不相关;您可以使用源代码中硬编码的一对 5x5x3 数组来演示相同的问题。对于这个问题,这将是一个更好的minimal, complete, verifiable example。如果你不能这样做,至少将 64x64x3 PNG 文件上传到某个地方,以便人们可以调试你的示例——但最好让它们变得不必要。 (我认为这是一个很好的问题,只是它可能是一个更好的问题。)

标签: python image-processing numpy


【解决方案1】:

看看data[data_mask == red]:它将是一个平面数组,而不是 (X,Y,3) 的 3D 数组。所以,最后一个轴是 5012,而不是 3。所以你不能广播分配。

The docs 解释一下:

结果是一个一维数组,其中包含索引数组中的所有元素,对应于布尔数组中的所有真实元素。

但是……

如果 y 的维度多于 b,则结果将是多维的。例如:

(这里,y 相当于您的data,而b 相当于您的red_mask。)

如果你仔细想想,这是有道理的。您的 red_mask 是一个 64x64x3 数组;它不可能挑选出 3 个向量(像素),它只能挑选出单个值。


让我们举一个更小、更简单、更具体的例子(一个 4 像素的一维数组,而不是一个 64x64 像素的二维数组),而不是你的例子(a)你没有给我们和(b ) 太大了,不能一下子看:

>>> data = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
>>> mask = np.array([[1,2,3], [4,5,6], [1,2,3], [4,5,6]])
>>> red = np.array([1,2,3])
>>> red_mask = mask == red
>>> red_mask
array([[ True,  True,  True],
       [False, False, False],
       [ True,  True,  True],
       [False, False, False]], dtype=bool)
>>> data[red_mask]
array([1, 2, 3, 7, 8, 9])
>>> data[red_mask] = [0,0,0]
ValueError: NumPy boolean array indexing assignment cannot assign 3 input values to the 6 output values where the mask is true
>>> red_mask[:,0]
array([ True, False,  True, False], dtype=bool)
>>> data[red_mask[:,0]]
array([[1, 2, 3],
       [7, 8, 9]])
>>> data[red_mask[:,0]] = [0,0,0]
>>> data
array([[ 0,  0,  0],
       [ 4,  5,  6],
       [ 0,  0,  0],
       [10, 11, 12]])

看到red_mask 是每个单独标量分量的索引,而red_mask[:,0] 是每个整个 3 向量像素的索引吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-17
    • 2017-05-20
    相关资源
    最近更新 更多