Маскировка Numpy в 3-канальном массиве

Следующий фрагмент создаст тестовое изображение

# Create 3x3x3 image
test_image = []
for i in range(9):
    if i < 6:
        image.append([255, 22, 96])
    else:
        image.append([255, 0, 0])

Вне:

array([[[255,  22,  96],
        [255,  22,  96],
        [255,  22,  96]],

       [[255,  22,  96],
        [255,  22,  96],
        [255,  22,  96]],

       [[255,   0,   0],
        [255,   0,   0],
        [255,   0,   0]]], dtype=int32)

Моя цель создать одноканальное изображение нулей НО для каждого [255, 22, 96] в test_image, я хочу установить число 100 в новом изображении single_channel:

Я пробовал следующее:

test_image = np.array(test_image)
height, width, channels = test_image.shape
single_channel_img = np.zeros(test_image.shape, dtype=int)

msk = test_image ==  [255, 22, 96] # DOES NOT WORK AS EXPECTED
single_channel_img[msk] = 100

Что не работает, потому что результат маскировки:

msk = test_image ==  [255, 22, 96]

возвращает:

array([[[ True,  True,  True],
        [ True,  True,  True],
        [ True,  True,  True]],

       [[ True,  True,  True],
        [ True,  True,  True],
        [ True,  True,  True]],

       [[ True, False, False],
        [ True, False, False],
        [ True, False, False]]])

Почему маскирование возвращает True для последних 3 пикселей и как я могу убедиться, что это сравнение возвращает True, только если все 3 значения одинаковы? Мое предположение заключалось в том, что способ, которым я маскирую, должен просто возвращать True, когда все 3 значения RGB равны [255, 22, 96].

Numpy не знает о пикселях. Он сравнивает элементы массива один за другим. Вы можете использовать all, чтобы уменьшить это. Я считаю, что msk.all(axis=2) должен это сделать. Он возвращает true, если все части верны.

Tim Roberts 19.11.2022 00:45

@TimRoberts это решило это для меня. Я действительно думал, что numpy выполняет сравнение по каналам, если я предоставляю список с 3 элементами внутри.

Joe Dawson 19.11.2022 00:54
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
2
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете преобразовать msk в трехмерный массив, используя вещание массива: https://numpy.org/doc/stable/user/basics.broadcasting.html

Команду .reshape можно использовать для изменения размеров массива. Numpy автоматически заполнит «тонкое» измерение. Так, например, сравнение массивов с фигурами (n,n,3) и (1,1,3) аналогично сравнению каждого подмассива test_image[i,j,:] с целью (1,1,3).

import  numpy as np

# Create 3x3x3 image
test_image = []
for i in range(9):
    if i < 6:
        test_image.append([255, 22, 96])
    else:
        test_image.append([255, 0, 0])

test_image         = np.array(test_image).reshape((3,3,3)) # test image shape needed to be fixed
single_channel_img = np.zeros(test_image.shape, dtype=int)

msk = test_image == np.array([255,22,96]).reshape((1,1,3)) # now it works
single_channel_img[msk] = 100

print(single_channel_img)
# [[[100 100 100]
#   [100 100 100]
#   [100 100 100]]
# 
#  [[100 100 100]
#   [100 100 100]
#   [100 100 100]]
# 
#  [[100   0   0]
#   [100   0   0]
#   [100   0   0]]]

PS. PyTorch также имеет широковещательную рассылку массивов, это действительно полезно в глубоком обучении.

Спасибо за хорошее объяснение. Теперь я могу правильно кодировать свои метки для сегментации изображения.

Joe Dawson 19.11.2022 01:03

Другие вопросы по теме