Подтвердить что ты не робот

Указание и сохранение фигуры с точным размером в пикселях

Скажем, у меня есть изображение размером 3841 x 7195 пикселей. Я хотел бы сохранить содержимое фигуры на диске, в результате получится образ точного размера, который я укажу в пикселях.

Нет оси, нет названий. Только изображение. Я лично не забочусь о DPI, так как я хочу только указать размер изображения, который занимает экран на диске в пикселях.

Я прочитал другие темы, и все они, кажется, делают преобразования в дюймах, а затем определяют размеры фигуры в дюймах и настройка dpi в некотором роде. Я бы хотел избежать возможности потери точности, которая может возникнуть в результате преобразования пикселей в дюймы.

Я пробовал с:

w = 7195
h = 3841
fig = plt.figure(frameon=False)
fig.set_size_inches(w,h)
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)
ax.imshow(im_np, aspect='normal')
fig.savefig(some_path, dpi=1)

не повезло (Python жалуется, что ширина и высота должны быть ниже 32768 (?))

Из всего, что я видел, matplotlib требует, чтобы размер фигуры указывался в inches и dpi, но меня интересует только пиксели, которые фигура занимает на диске. Как я могу это сделать?

Чтобы уточнить: я ищу способ сделать это с помощью matplotlib, а не с другими библиотеками для сохранения изображений.

4b9b3361

Ответ 1

Matplotlib не работает с пикселями напрямую, а скорее с физическими размерами и DPI. Если вы хотите отобразить фигуру с определенным размером пикселя, вам необходимо знать DPI вашего монитора. Например эта ссылка обнаружит это для вас.

Если у вас есть изображение 3841x7195 пикселей, маловероятно, что вы сделаете так, чтобы монитор был таким большим, поэтому вы не сможете отобразить фигуру такого размера (matplotlib требует, чтобы фигура поместилась на экране, если вы спросите для слишком большого размера он будет уменьшаться до размера экрана). Представьте себе, что вы хотите получить изображение 800x800 пикселей для примера. Здесь, как показать изображение 800x800 пикселей на моем мониторе (my_dpi=96):

plt.figure(figsize=(800/my_dpi, 800/my_dpi), dpi=my_dpi)

Итак, вы просто разделите размеры в дюймах своим DPI.

Если вы хотите сохранить фигуру определенного размера, тогда это другое дело. Экранные DPI не так важны (если вы не попросите цифру, которая не будет вписываться в экран). Используя тот же пример 800x800 пикселей, мы можем сохранить его в разных разрешениях с помощью ключевого слова dpi savefig. Чтобы сохранить его в том же разрешении, что и на экране, используйте только те же dpi:

plt.savefig('my_fig.png', dpi=my_dpi)

Чтобы сохранить его как изображение размером 8000x8000 пикселей, используйте dpi в 10 раз больше:

plt.savefig('my_fig.png', dpi=my_dpi * 10)

Обратите внимание, что настройка DPI не поддерживается всеми бэкэндами. Здесь используется бэкэнд PNG, но бэкенды pdf и ps будут реализовывать размер по-разному. Кроме того, изменение DPI и размеров также повлияет на такие вещи, как fontsize. Более крупный DPI будет поддерживать одинаковые относительные размеры шрифтов и элементов, но если вам нужны более мелкие шрифты для увеличения фигуры, вам нужно увеличить физический размер вместо DPI.

Возвращаясь к вашему примеру, если вы хотите сохранить изображение с 3841 x 7195 пикселями, вы можете сделать следующее:

plt.figure(figsize=(3.841, 7.195), dpi=100)
( your code ...)
plt.savefig('myfig.png', dpi=1000)

Обратите внимание, что я использовал цифру dpi 100, чтобы соответствовать большинству экранов, но сохранялся с помощью dpi=1000 для достижения требуемого разрешения. В моей системе это создает png с 3840x7190 пикселями - кажется, что DPI сохранен всегда на 0,02 пикселя на дюйм меньше выбранного значения, которое будет иметь (небольшое) влияние на большие размеры изображения. Еще несколько обсуждений этого здесь.

Ответ 2

Это сработало для меня, основываясь на вашем коде, создавая PNG-изображение 93Mb с цветовым шумом и требуемыми размерами:

import matplotlib.pyplot as plt
import numpy

w = 7195
h = 3841

im_np = numpy.random.rand(h, w)

fig = plt.figure(frameon=False)
fig.set_size_inches(w,h)
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)
ax.imshow(im_np, aspect='normal')
fig.savefig('figure.png', dpi=1)

Я использую последние версии PIP для библиотек Python 2.7 в Linux Mint 13.

Надеюсь, что это поможет!