Использовать NumPy, чтобы замаскировать изображение с рисунком? - PullRequest
18 голосов
/ 31 января 2010

Я использую NumPy для создания пиксельных массивов. Изображение 800x600 - это трехмерный массив uint8, 800x600x3. У меня также есть аналогичный массив с фиксированным шаблоном (шахматная доска, см. здесь ). У меня есть другой массив, 800x600 значений маски. Там, где маска равна нулю, я хочу скопировать пиксель шаблона в пиксель изображения. Там, где маска не равна нулю, я хочу оставить пиксель изображения в покое.

>>> image.shape
(800, 600, 3)
>>> chex.shape
(800, 600, 3)
>>> mask.shape
(800, 600)

Такое ощущение, что должно работать:

image[mask == 0,...] = chex

но выдает «ValueError: массив не транслируется для правильной формы».

Что я использую для копирования пикселей chex в пиксели изображения, где маска равна нулю?

Ответы [ 5 ]

21 голосов
/ 31 января 2010
idx=(mask==0)
image[idx]=chex[idx]

Обратите внимание, что image имеет форму (800 600,3), а idx имеет форму (800 600). Правила для индексации состояния

если кортеж выбора меньше чем n, то столько объектов: сколько нужно добавляются к концу выбора кортеж так, чтобы измененный выбор кортеж имеет длину N.

Таким образом, индексные массивы обладают своего рода способностью вещания. Форма idx повышена до (800,600,:)

3 голосов
/ 21 мая 2018

Я хотел бы проиллюстрировать пример, используя ответ @unutbu. В этом сценарии у меня есть изображение кошки, которую я вращаю. Это вращение вызывает появление черных краев, которые выглядят некрасиво, особенно при вставке на не черный фон.

import matplotlib.pyplot as plt
from scipy.ndimage import rotate


cat = plt.imread('cat.jpeg')
bg = plt.imread('background.jpeg')


rotcat = rotate(cat, angle=8, reshape=True) ## rotating creates some black edges
height, width, _ = rotcat.shape

bgcopy = bg.copy() ## create a copy of the background; paste on copy

x, y = 40, 50 
bgcopy[x:x+height, y:y+width] = rotcat
plt.imsave('cat-on-bg-mask.jpg', bgcopy)

bad pasting

Итак, я нахожу области маски и заменяю эти значения исходными значениями фона

mask_ind = (bgcopy == 0)
bgcopy[mask_ind] = bg[mask_ind]
plt.imsave('cat-on-bg.jpg', bgcopy)

good pasting

Следует также отметить, что PIL.Image (из библиотеки Pillow) имеет возможность вставлять изображение в другое изображение за меньшее количество шагов.

0 голосов
/ 21 мая 2019

Мне было проще всего создать маску, в которой 1 = «пиксель сохранить» и 0 = «пиксель удалить».

Затем я умножил свое изображение на эту маску, чтобы удалить ненужные пиксели. Пример сохранения только рамки (снаружи) портрета:

from scipy.misc import imread
import matplotlib.pyplot as plt
import numpy as np

im = imread('portrait.jpg', mode='L') # read in image
plt.imshow(im) # show the original image

enter image description here

mask = np.ones(im.shape) # create a mask with the image's shape
bw = 0.1 # identify border width and height as fraction of image size
bx = int(im.shape[1] * bw) # get the x dimension border width
by = int(im.shape[0] * bw) # get the y dimension border height
mask[bx:-bx,by:-by] = 0 # create a mask with 1 for border and 0 for inside

masked = im * mask # multiply `im` by the mask to zero out non-border pixels
plt.imshow(masked) # show the result of the masking operation

enter image description here

0 голосов
/ 31 января 2010

Я использовал массивы 8x6x3, 8x6x3 и 8x6 для представления вашего массива изображения, массива проверки и массива маски соответственно.

# first create mini-versions of your arrays:
mask = NP.random.random_integers(0, 1, 48).reshape(8, 6)
img = NP.random.random_integers(3, 9, 8*6*3).reshape(8, 6, 3)
chk = NP.ones((8, 6, 3))

# all the work done in these two lines
mask = mask[:,:,NP.newaxis]
res = NP.where(mask==0, chk, img)
0 голосов
/ 31 января 2010

Попробуйте:

image[mask[:] == 0,...] = chex[mask[:] == 0,...]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...