2015-04-20 3 views
2

Описание

У меня есть изображение и его маска. Я использую 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 

Я что-то упускаю? Как я могу использовать идею масок массива для изменения значений пикселей?

+3

Это не ваша проблема, но если вы используете 'import Image', а не' from PIL import Image', это означает, что вы используете PIL, а не свою современную подушку для вилки. Если вам действительно не нужна обратная совместимость с очень старыми версиями Python или с кодом, который по какой-то причине не будет работать с Pillow (такого не должно быть, но всегда есть ошибки, верно?), Не делайте что. – abarnert

+1

Для справок в будущем: материал PIL здесь не имеет отношения; вы можете продемонстрировать ту же проблему, например, с парой массивов 5x5x3, жестко закодированных в источнике. Это сделало бы лучший [минимальный, полный, проверяемый пример] (http://stackoverflow.com/help/mcve) для этой проблемы. Если вы не можете этого сделать, по крайней мере, загрузите файлы PNG размером 64x64x3, чтобы люди могли отлаживать ваш пример, но даже лучше сделать их ненужными. (Я думаю, что это был хороший вопрос, просто он может быть еще лучше). – abarnert

ответ

4

Посмотрите на data[data_mask == red]: это будет плоский массив, а не 3D-массив (X, Y, 3). Таким образом, последняя ось 5012, а не 3. Таким образом, вы не можете транслировать задание.

The docs объяснить:

В результате 1-D, содержащий массив из всех элементов в индексном массиве, соответствующий все истинные элементы в массиве булева.

Но ...

Результат будет многомерным, если у имеет больше измерений, чем б. Например:

(Здесь y является эквивалентом ваших data и b из ваших red_mask.)

Если вы думаете об этом, это имеет смысл. Ваш red_mask - массив 64x64x3; он не может выбрать 3-векторы (пиксели), он может выбирать только отдельные значения.


Давайте меньше, более простой, конкретный пример (в 1D массив 4 пикселей, вместо 2D-массив 64x64 пикселей), вместо того, чтобы ваш пример, который (а) вы не дали нам данные для и (б) слишком велик, чтобы посмотреть на все сразу:

>>> 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-вектор пикселя?

Смежные вопросы