Предположим, у меня есть изображение в оттенках серого: введите описание изображения здесь

И здесь двоичное замаскированное изображение: введите здесь описание изображения

С такими же размерами и формой. Как мне сгенерировать что-то вроде этого: введите здесь описание изображения

Где значения, обозначенные 1 в двоичной маске, являются действительными значениями, а значения, которые равны 0 в маске, являются нулевыми в конечном изображении.

6
Sibh 21 Дек 2019 в 02:25
Умножить их?
 – 
Paul Panzer
21 Дек 2019 в 02:33
2
Это не изображения в оттенках серого.
 – 
Marcin Orlowski
21 Дек 2019 в 04:29
Я использую matplotlib с палитрой viridis, поэтому они не будут серыми, но они не rgb.
 – 
Sibh
21 Дек 2019 в 04:42
Ваши изображения не одинакового размера. Также, пожалуйста, всегда размещайте правильное изображение без цветовой карты; в противном случае вы запутаете людей и усложните демонстрацию решения для изображений в градациях серого.
 – 
fmw42
14 Ноя 2020 в 00:12

3 ответа

Используйте cv2.bitwise_and, чтобы замаскируйте изображение бинарной маской. Любые белые пиксели на маске (значения с 1) будут сохранены, а черные пиксели (значение с 0) будут проигнорированы. Вот пример:

Входное изображение (слева), маска (справа)

Результат после маскировки

Код

import cv2
import numpy as np

# Load image, create mask, and draw white circle on mask
image = cv2.imread('1.jpeg')
mask = np.zeros(image.shape, dtype=np.uint8)
mask = cv2.circle(mask, (260, 300), 225, (255,255,255), -1) 

# Mask input image with binary mask
result = cv2.bitwise_and(image, mask)
# Color background white
result[mask==0] = 255 # Optional

cv2.imshow('image', image)
cv2.imshow('mask', mask)
cv2.imshow('result', result)
cv2.waitKey()
5
nathancy 21 Дек 2019 в 03:15

Вот два других способа использования Python Opencv. Первый похож на @nathancy. Второй использует умножение для маскировки. Я использую те же изображения, что и @nathancy:

enter image description here

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread('pink_flower.png')

#mask it - method 1:
# read mask as grayscale in range 0 to 255
mask1 = cv2.imread('pink_flower_mask.png',0)
result1 = img.copy()
result1[mask1 == 0] = 0
result1[mask1 != 0] = img[mask1 != 0]

# mask it - method 2:
# read mask normally, but divide by 255.0, so range is 0 to 1 as float
mask2 = cv2.imread('pink_flower_mask.png') / 255.0
# mask by multiplication, clip to range 0 to 255 and make integer
result2 = (img * mask2).clip(0, 255).astype(np.uint8)

cv2.imshow('image', img)
cv2.imshow('mask1', mask1)
cv2.imshow('masked image1', result1)
cv2.imshow('masked image2', result2)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save results
cv2.imwrite('pink_flower_masked1.png', result1)
cv2.imwrite('pink_flower_masked2.png', result2)


Результаты одинаковы для обоих методов:

enter image description here

2
fmw42 21 Дек 2019 в 04:13

Другие ответы не помогли мне. Тогда я потратил так много времени, чтобы найти хорошую маскирующую функцию. Вот два простых ответа только с numpy.

import numpy as np

arr = np.arange(27).reshape(3,3,3) #3 channel image
mask = np.zeros(shape=(3,3))
mask[1,1] = 1 # binary mask
mask_3d = np.stack((mask,mask,mask),axis=0) #3 channel mask

## Answer 1
# Simply multiply the image array with the mask

masked_arr = arr*mask_3d

## Answer 2
# Use the where function in numpy

masked_arr = np.where(mask_3d==1,arr,mask_3d)

#Both answer gives
print(masked_arr)

array([[[ 0.,  0.,  0.],
        [ 0.,  4.,  0.],
        [ 0.,  0.,  0.]],

       [[ 0.,  0.,  0.],
        [ 0., 13.,  0.],
        [ 0.,  0.,  0.]],

       [[ 0.,  0.,  0.],
        [ 0., 22.,  0.],
        [ 0.,  0.,  0.]]])
0
Prefect 13 Ноя 2020 в 22:03