Numpy.putmask с изображениями - PullRequest
       3

Numpy.putmask с изображениями

3 голосов
/ 04 апреля 2011

У меня есть изображение, преобразованное в ndarray со значениями RGBA. Предположим, что это 50 х 50 х 4.

Я хочу заменить все пиксели значениями array([255, 255, 255, 255]) для array([0, 0, 0, 0]). Итак:

from numpy import *
from PIL import Image
def test(mask):
        mask = array(mask)
        find = array([255, 255, 255, 255])
        replace = array([0, 0, 0, 0])
        return putmask(mask, mask != find, replace)

mask = Image.open('test.png')
test(mask)

Что я делаю не так? Это дает мне ValueError: putmask: mask and data must be the same size. Тем не менее, если я изменю массивы на числа (find = 255, replace = 0), это сработает.

Ответы [ 3 ]

4 голосов
/ 04 апреля 2011

Более краткий способ сделать это:

img = Image.open('test.png')
a = numpy.array(img)
a[(a == 255).all(axis=-1)] = 0
img2 = Image.fromarray(a, mode='RGBA')

В общем, если элементы find и repl не являются одинаковыми, вы также можете сделать

find = [1, 2, 3, 4]
repl = [5, 6, 7, 8]
a[(a == find).all(axis=-1)] = repl
2 голосов
/ 04 апреля 2011

В этом решении используется putmask, и я думаю, что он наиболее близок к коду OP.В исходном коде есть две ошибки, о которых OP должен знать: 1) putmask - операция на месте.Возвращает None.2) putmask также требует массивов одинакового размера.У него (очень плохо) нет ключевого аргумента axis.

import numpy as np
from PIL import Image

img1 = Image.open('test.png')
arry = np.array(img1)
find = np.array([255, 255, 255, 255])
repl = np.array([  0,   0,   0,   0])
# this is the closest to the OPs code I could come up with that
# compares each pixel array with the 'find' array
mask = np.all(arry==find, axis=2)
# I iterate here just in case repl is not always the same value
for i,rep in enumerate(repl):
    # putmask works in-place - returns None
    np.putmask(arry[:,:,i], mask, rep)

img2 = Image.fromarray(arry, mode='RGBA')
img2.save('testx.png')
2 голосов
/ 04 апреля 2011

Один из способов такого маскирования каналов - разделить массив на каналы r, g, b, а затем определить индекс с помощью операций с логическими битами:

import numpy as np
import Image

def blackout(img):
    arr = np.array(img)
    r,g,b,a=arr.T
    idx = ((r==255) & (g==255) & (b==255) & (a==255)).T
    arr[idx]=0
    return arr

img = Image.open('test.png')
mask=blackout(img)
img2=Image.fromarray(mask,mode='RGBA')
img2.show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...