1. Я использую cv2.imread для чтения большого изображения в массиве numpy (1234 * 1624 * 3)
2. Я использую cv2.dnn.blobFromImage, чтобы преобразовать его в (1,3,1234,1624) массив numpy
3. Я использую tolist(), чтобы преобразовать его в 4D-список в списках.
Моя проблема:
Как транспонировать ось этого списка
от (1,3,1234,1624) до (1,1234,1624,3)?
Сначала я попробовал np.transpose(image, (0, 2, 3, 1)), а затем tolist(), но это оказалось очень медленным. Поэтому я хочу транспонировать в виде списка.
Я проверил вопрос ниже, он кажется быстрым, но может транспонировать только 2D-список Транспонировать список списков
Очень признателен!!
Обновлять:
У меня есть список с именем temp.
len(temp)=1len(temp[0])=3len(temp[0][0])=1234len(temp[0][0][0])=1624
и я хочу перенести его ось на
len(temp)=1len(temp[0])=1234len(temp[0][0])=1624len(temp[0][0][0])=3
Как быть с temp1=list(map(list, zip(*temp))?
Я пробовал temp1=list(map(list, zip(zip(*temp)))) но у меня не работает
Извините, я неправильно понял, трюк с двойным zip работает только для итераторов вложенности 1 уровня. Я думаю, что NumPy самый быстрый. Зачем вам нужно конвертировать его в list?
Мне нужно отправить запрос в формате Json на обслуживание Tensorflow. Я обнаружил, что ndnumpy (1,3,1234,1624).tolist() намного быстрее, чем ndnumpy (1,1234,1624,3).tolist()
(1,3,1234,1624) - это форма массива ndnumpy
Этот массив транспонируется, np.transpose(image, (0, 2, 3, 1)) должен быть быстрым, так как он создает представление, а не копию. Выполнение tolist() на tolist может быть немного медленнее (чем image на np.transpose(image, (0, 2, 3, 1))), потому что оно, вероятно, включает копирование. Но это должно быть проще и быстрее, чем пытаться сделать эквивалентное транспонирование со списками.
Я знаком с идиомой zip* для транспонирования простого вложенного списка, я бы поэкспериментировал, чтобы придумать эквивалент для этого четырехмерного вложения (на самом деле трехмерного, поскольку мы можем игнорировать первый размер одного измерения). Даже с этим я, вероятно, буду проверять свои результаты на версии с массивом, что легко понять.
np.transpose(image, (0, 2, 3, 1)) очень быстро. Однако выполнение tolist() в массиве (1,1234,1624,3) numpy занимает в 5 раз больше, чем tolist() в массиве (1,3,1234,1624) numpy на моей машине.
Создание вложенного списка с этим небольшим внутренним размером 3 будет дорогостоящим, как бы вы это ни делали. У вас будет миллион лиатов размером 3 и указатели на каждый.
@hpaulj, не могли бы вы поделиться своим кодом? Большое спасибо!






Это можно сделать без numpy и чисто функционально, но это некрасиво:
from itertools import starmap, repeat
a = np.ones((1,3,1234,1624)).tolist()
b = list(map(list, map(map, repeat(list), map(starmap, repeat(zip), starmap(zip, a)))))
np.shape(b)
# (1, 1234, 1624, 3)
Спасибо за ответ! np.ones((1,3,1234,1624)).tolist()+list(map(list, map(map, repeat(list), map(starmap, repeat(zip), starmap(zip, a))))) занимает только половину времени np.transpose(image, (0, 2, 3, 1))+tolist() на моей машине! Это много!
Тем не менее, я немного смущен тем, как работает эта карта и почтовый индекс. Можете ли вы просто объяснить, хочу ли я обобщить список N-D другой формы?
@BillHuang Боюсь, это то, на что я способен. Я не думаю, что это хорошо обобщает (выражения становятся все длиннее и длиннее). Что касается объяснения. Мы можем поменять местами только соседние оси с помощью zip, поэтому мы должны построить желаемое перемешивание из таких обменов. Обмены выглядят следующим образом: поменять местами оси 0 и 1: zip(*a) ; поменять местами оси 1 и 2: starmap(zip, a) ; поменять местами оси 2 и 3: map(starmap, repeat(zip), a) и т. д. В Python3 все эти генераторы возвращают значения, поэтому нам нужно форсировать списки на дополнительном шаге.
Итак, начинаем --> (1, 3, 1234, 1624) Далее,starmap(zip, a) --> (1, 1234, 3, 1624) (поменяем местами оси 1 и 2) Далее,map(starmap, repeat(zip), starmap(zip, a))) --> (1, 1234, 1624, 3) (поменяем местами оси 2 и 3) Я правильно понимаю? Тогда что map(list, map(map, repeat(list), ) делает снаружи? Большое спасибо за Ваш ответ! @PaulPanzer
@BillHuang да, пока это правильно. Как я уже сказал, они создают не списки, а генераторы. Генератор - это что-то вроде "приостановленного цикла for", вам нужно перебрать его или сопоставить со списком или кортежем, иначе он ничего не делает. Как и в случае со свопами, эти генераторы создаются с разной глубиной вложенности, поэтому нам приходится администрировать приведение list через maps и вложенные maps.
Используйте идиоматическое выражение
zip(*zip(*items))