Я пишу программную систему, которая визуализирует срезы и проекции через набор 3D-данных. Я использую matplotlib
и специально imshow
для визуализации буферов изображений, которые я получаю из своего кода анализа.
Поскольку я хочу аннотировать изображения с помощью осей графика, я использую ключевое слово extension, которое imshow
предоставляет для сопоставления пиксельных координат буфера изображения с системой координат пространства данных.
К сожалению, matplotlib
насчет единиц не знает. Скажем (взяв искусственный пример), что я хочу построить изображение размером 1000 m X 1 km
. В этом случае степень будет примерно такой [0, 1000, 0, 1]
. Несмотря на то, что массив изображений является квадратным, поскольку соотношение сторон, подразумеваемое ключевым словом extension, равно 1000, итоговые оси графика также имеют соотношение сторон 1000.
Можно ли изменить соотношение сторон графика, сохраняя при этом автоматически сгенерированные основные отметки и метки, которые я получаю с помощью ключевого слова экстента?
источник
scalar
варианте. Кажется, масштабируетсяy-axis
заданным скаляром.Из
plt.imshow()
официального руководства мы знаем, что аспект определяет соотношение сторон осей. Ну в моих словах, аспект именно отношение х единиц и у блока . В большинстве случаев мы хотим оставить его равным 1, так как мы не хотим непреднамеренно искажать цифры. Однако действительно есть случаи, когда нам нужно указать аспектное значение, отличное от 1. Автор вопроса привел хороший пример того, что оси x и y могут иметь разные физические единицы. Предположим, что x указано в км, а y - в метрах. Следовательно, для данных 10x10 протяженность должна быть [0,10 км, 0,10 м] = [0, 10000 м, 0, 10 м]. В таком случае, если мы продолжим использовать аспект по умолчанию = 1, качество рисунка будет действительно плохим. Следовательно, мы можем указать аспект = 1000, чтобы оптимизировать нашу фигуру. Следующие коды иллюстрируют этот метод.%matplotlib inline import numpy as np import matplotlib.pyplot as plt rng=np.random.RandomState(0) data=rng.randn(10,10) plt.imshow(data, origin = 'lower', extent = [0, 10000, 0, 10], aspect = 1000)
Тем не менее, я думаю, что есть альтернатива, способная удовлетворить требования вопрошающего. Мы можем просто установить размер как [0,10,0,10] и добавить дополнительные метки оси xy для обозначения единиц. Коды следующие.
plt.imshow(data, origin = 'lower', extent = [0, 10, 0, 10]) plt.xlabel('km') plt.ylabel('m')
Чтобы составить правильную цифру, всегда нужно иметь в виду то
x_max-x_min = x_res * data.shape[1]
иy_max - y_min = y_res * data.shape[0]
, гдеextent = [x_min, x_max, y_min, y_max]
. По умолчанию этоaspect = 1
означает, что пиксель единицы квадратный. Это поведение по умолчанию также отлично работает для x_res и y_res, которые имеют разные значения. Расширяя предыдущий пример, предположим, что x_res равно 1,5, а y_res равно 1. Следовательно, размер должен быть равен [0,15,0,10]. Используя формат по умолчанию, мы можем иметь прямоугольные цветные пиксели, тогда как единичный пиксель по-прежнему квадратный!plt.imshow(data, origin = 'lower', extent = [0, 15, 0, 10]) # Or we have similar x_max and y_max but different data.shape, leading to different color pixel res. data=rng.randn(10,5) plt.imshow(data, origin = 'lower', extent = [0, 5, 0, 5])
Аспект цветного пикселя
x_res / y_res
. установка его формата на единичный пиксель (т.е.aspect = x_res / y_res = ((x_max - x_min) / data.shape[1]) / ((y_max - y_min) / data.shape[0])
) всегда будет давать квадратный цветной пиксель. Мы можем изменить аспект = 1.5 так, чтобы единица измерения по оси x была в 1,5 раза больше единицы по оси y, что привело бы к квадратному цветному пикселю и квадратной целой фигуре, но прямоугольной единице пикселей. Видимо, это обычно не принято.data=rng.randn(10,10) plt.imshow(data, origin = 'lower', extent = [0, 15, 0, 10], aspect = 1.5)
Самым нежелательным случаем является то, что аспекту задается произвольное значение, например 1,2, что не приведет ни к квадратным единичным пикселям, ни к квадратным цветным пикселям.
plt.imshow(data, origin = 'lower', extent = [0, 15, 0, 10], aspect = 1.2)
Короче говоря, всегда достаточно установить правильный экстент и позволить matplotlib делать остальное за нас (даже если x_res! = Y_res)! Меняйте вид только тогда, когда это необходимо.
источник