Как реализовать перетасовку пикселей

В тензорном потоке есть метод перемешивания пикселей, который называется deep_to_space. Он делает следующее: Предположим, у нас есть изображение (массив) размеров (4,4,4). Приведенный выше метод перемешивает значения этого массива, чтобы мы получили массив размером (16,16,1), как показано на изображении ниже:

В течение нескольких часов я пытался воссоздать этот метод в numpy, используя функции plane numpy, такие как изменение формы, транспонирование и т. д., однако мне это не удалось. Кто-нибудь знает, как это реализовать?

Очень похожую проблему можно найти в Как реализовать tf.space_to_length с помощью numpy?. Однако в этом вопросе рассматривается метод space_to_depth, который является обратной операцией.

Можете ли вы предоставить некоторые примерные данные просто в качестве примера?

Andrew Yim 29.07.2024 16:29

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

Mercury 30.07.2024 04:32

@Меркурий Согласен. Я добавил einops.rearrange решение к своему ответу.

simon 30.07.2024 09:57
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
3
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вот решение «сначала каналы» (т.е. при условии, что размеры вашего массива упорядочены каналы×высота×ширина):

import numpy as np

# Create some data ("channels-first" version)
a = (np.ones((1, 3, 3), dtype=int) *
     np.arange(1,5)[:, np.newaxis, np.newaxis])  # 4×3×3

c, h, w = a.shape  # channels, height, width
p = int(np.sqrt(c))  # height and width of one "patch"
assert p * p == c  # Sanity-check
a_flat = a.reshape(p, p, h, w).transpose(2, 0, 3, 1).reshape(h * p, w * p)  # 6×6

print(a)
# [[[1 1 1]
#   [1 1 1]
#   [1 1 1]]

#  [[2 2 2]
#   [2 2 2]
#   [2 2 2]]

#  [[3 3 3]
#   [3 3 3]
#   [3 3 3]]

#  [[4 4 4]
#   [4 4 4]
#   [4 4 4]]]

print(a_flat)
# [[1 2 1 2 1 2]
#  [3 4 3 4 3 4]
#  [1 2 1 2 1 2]
#  [3 4 3 4 3 4]
#  [1 2 1 2 1 2]
#  [3 4 3 4 3 4]]

А вот соответствующая версия «последние каналы» (т. е. при условии, что размеры вашего массива упорядочены по высоте×ширине×каналов):

import numpy as np

# Create some data ("channels-last" version)
a = np.ones((3, 3, 1), dtype=int) * np.arange(1, 5)  # 3×3×4

h, w, c = a.shape  # height, width, channels
p = int(np.sqrt(c))  # height and width of one "patch"
assert p * p == c  # Sanity-check
a_flat = a.reshape(h, w, p, p).transpose(0, 2, 1, 3).reshape(h * p, w * p)  # 6×6

print(a)
# [[[1 2 3 4]
#   [1 2 3 4]
#   [1 2 3 4]]

#  [[1 2 3 4]
#   [1 2 3 4]
#   [1 2 3 4]]

#  [[1 2 3 4]
#   [1 2 3 4]
#   [1 2 3 4]]]

print(a_flat)
# [[1 2 1 2 1 2]
#  [3 4 3 4 3 4]
#  [1 2 1 2 1 2]
#  [3 4 3 4 3 4]
#  [1 2 1 2 1 2]
#  [3 4 3 4 3 4]]

В обоих случаях идея одна и та же:

  1. С помощью первого reshape мы разделяем размер канала (или «глубину») длины c на то, что станет патчем p×p (обратите внимание, что p·p=c, где p и c соответствуют t и t² в вопросе).
  2. С помощью transpose мы размещаем высоту патча позади текущей высоты изображения, а ширину патча позади текущей ширины изображения.
  3. С помощью второго reshape мы объединяем текущую высоту изображения и высоту патча с новой высотой изображения, а текущую ширину изображения и ширину патча с новой шириной изображения.

Обновление: использование einops

Используя rerange() из пакета einops, как предложено в комментарии Mercury, соответствующие решения могут выглядеть следующим образом:

import numpy as np
from einops import rearrange

# Channels first
a = (np.ones((1, 3, 3), dtype=int) *
     np.arange(1,5)[:, np.newaxis, np.newaxis])  # 4×3×3
p = int(np.sqrt(a.shape[0]))  # height and width of one "patch"
a_flat = rearrange(a, "(hp wp) h w -> (h hp) (w wp)", hp=p)

# Channels last
a = np.ones((3, 3, 1), dtype=int) * np.arange(1, 5)  # 3×3×4
p = int(np.sqrt(a.shape[-1]))  # height and width of one "patch"
a_flat = rearrange(a, "h w (hp wp) -> (h hp) (w wp)", hp=p)

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