Использовать numpy для маскировки изображения с помощью шаблона?
Я использую numpy для создания пиксельных массивов. Изображение 800x600 представляет собой трехмерный массив uint8, 800x600x3. У меня также есть аналогичный массив с фиксированным рисунком (шахматная доска, см. здесь). У меня есть другой массив, 800x600 значений маски. Если маска равна нулю, я хочу скопировать пиксель образца в пиксель изображения. Если маска не равна нулю, я хочу оставить один пиксель изображения.
>>> image.shape
(800, 600, 3)
>>> chex.shape
(800, 600, 3)
>>> mask.shape
(800, 600)
Похоже, что он должен работать:
image[mask == 0,...] = chex
но дает "ValueError: массив не доступен для правильной формы".
Что я могу использовать для копирования пикселей в пикселях в пикселях изображений, где маска равна нулю?
Ответы
Ответ 1
idx=(mask==0)
image[idx]=chex[idx]
Обратите внимание, что image
имеет форму (800,600,3), а idx
имеет форму (800 600). Правила для индексации состояния
если кортеж выбора меньше, чем n, то столько: объектов по мере необходимости добавляются к концу выбора кортеж, чтобы измененный выбор кортеж имеет длину N.
Таким образом, массивы индексирования имеют свою собственную способность вещания. Форма idx
получает статус (800 600,:)
Ответ 2
Я хотел проиллюстрировать пример, используя ответ @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
) имеет возможность вставлять изображение в другое изображение с меньшим количеством шагов.
Ответ 3
Try:
image[mask[:] == 0,...] = chex[mask[:] == 0,...]
Ответ 4
Я использовал массивы 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)
Ответ 5
Я обнаружил, что проще всего создать маску, в которой 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 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]()