У меня возникли проблемы с использованием Pyplot imshow для построения изображения из numpy ndarray под названием data, сохраняя как соотношение сторон, так и пиксели квадратной формы. Форма ndarray - (112, 2182). Вот код, который я использую:
import matplotlib as mpl
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np
mpl.use('Agg')
import matplotlib.pyplot as plt
data = np.random.random_sample((112, 2182))
plt.figure(figsize=(25, 3.5))
plt.subplots_adjust(left=0.1, right=0.9)
ax = plt.subplot(111)
plt.axis('off')
plt.title('Title', fontweight='bold', y=1.15)
im = ax.imshow(data)
# Add same-width colorbar to the bottom of the image
divider = make_axes_locatable(ax)
cax = divider.append_axes("bottom", size="25%", pad=0.3)
cbar = plt.colorbar(im, orientation="horizontal", cax=cax)
# Save image
plt.savefig('image.pdf', dpi=1000, format=pdf)
Я думал, что, установив соотношение сторон с помощью формы ndarray, изображение будет показывать квадратные пиксели. Однако изображение, кажется, сохраняет соотношение сторон, но пиксели не являются квадратами, как вы можете видеть на увеличенном изображении (я все еще не могу публиковать изображения, извините):
увеличенный график
весь сюжет
Эти результаты такие же, как у меня, когда я использовал im = ax.imshow(data) без аргумента aspect. Я вручную посчитал пиксели по оси Y всего графика, и их 112, так что дело не в группировке пикселей. Любые идеи о том, как решить эту проблему?
РЕДАКТИРОВАТЬ: изображение, которое я рисую, также будет иметь цветную полосу и заголовок. Кроме того, мне нужно иметь возможность сохранить его в файл PDF. Увеличенный график, который я загрузил, представляет собой снимок экрана, увеличенный в программе просмотра PDF.
Ответ 1 · рейтинг 2 · ImportanceOfBeingErnest
Если вы используете ax.imshow(data), вы автоматически получите квадратные пиксели. Если вместо этого вы установите аспект, отличный от 1/"equal", вы не получите квадратных пикселей. Это, однако, не зависит от эффекта, наблюдаемого в вопросе.
Проблема в "увеличенном изображении" заключается в том, что размер пикселей данных порядка фактических пикселей экрана. Следовательно, размер пикселей изображения может варьироваться на столько же, сколько пиксель экрана. Решение этой проблемы состоит в том, чтобы сэкономить на фигуре, так что один пиксель изображения равен ровно одному экранному пикселю или любому кратному ему.
В этом случае это будет так же просто, как
data = np.random.random_sample((2182, 112))
plt.imsave("filename.png", data)
Ответ 2 · Community
Вам необходимо масштабировать пиксели с использованием параметров imshow: форма и экстент:
import numpy as np
import matplotlib.pyplot as plt
shape = (112, 2182)
extent = [0, 112, 0, 2182]
data = np.random.random_sample(shape)
plt.figure(figsize=(5, 3.5))
ax = plt.subplot(111)
plt.axis('off')
dx = (extent[1] - extent[0]) / shape[1]
dy = (extent[3] - extent[2]) / shape[0]
dx_dy = dx/dy
im = ax.imshow(data, extent=extent, aspect=dx_dy)
plt.show()
Ответ 3 · Christian K.
В документации сказано, что параметр aspect может быть числом с плавающей запятой или
'equal': обеспечивает соотношение сторон, равное 1. Пиксели будут квадратными (если размеры пикселей явно не сделаны неквадратными в координатах данных с использованием экстента).
"авто": оси остаются фиксированными, а соотношение сторон регулируется таким образом, чтобы данные соответствовали осям. Как правило, это приводит к неквадратным пикселям.
Таким образом, соотношение сторон 1,0 - это то, что вам нужно. Не ожидается, что вы получите вывод, показанный выше, с учетом значения, которое вы вычислили из формы массива. Как указывает @ImportanceOfBeingErnest, aspect='equal' используется по умолчанию, так что это так же просто, как
im = ax.imshow(data)