Імшоу: ступінь та аспект


85

Я пишу програмну систему, яка візуалізує фрагменти та проекції за допомогою 3D-набору даних. Я використовую matplotlibі спеціально imshowдля візуалізації буферів зображень, які я отримую з мого коду аналізу.

Оскільки я хотів би анотувати зображення осями графіків, я використовую ключове слово екстенс, яке imshowпостачає, щоб зіставити координати пікселів буфера зображення із системою координат простору даних.

На жаль, matplotlibне знає про одиниці. Скажіть (беручи штучний приклад), що я хочу побудувати зображення з розмірами1000 m X 1 km . У цьому випадку екстент буде приблизно таким [0, 1000, 0, 1]. Незважаючи на те, що масив зображень квадратний, оскільки співвідношення сторін, що передбачається ключовим словом екстенс, дорівнює 1000, отримані осі ділянки також мають співвідношення сторін 1000.

Чи можна примусити співвідношення сторін сюжету, зберігаючи автоматично генеровані основні позначки та мітки, які я отримую, використовуючи ключове слово екстенс?

Відповіді:


141

Ви можете зробити це, встановивши аспект зображення вручну (або дозволивши йому автоматично масштабувати, щоб заповнити розмір малюнка).

За замовчуванням imshowвстановлює аспект сюжету на 1, оскільки це часто те, що люди хочуть для даних зображень.

У вашому випадку ви можете зробити щось на зразок:

import matplotlib.pyplot as plt
import numpy as np

grid = np.random.random((10,10))

fig, (ax1, ax2, ax3) = plt.subplots(nrows=3, figsize=(6,10))

ax1.imshow(grid, extent=[0,100,0,1])
ax1.set_title('Default')

ax2.imshow(grid, extent=[0,100,0,1], aspect='auto')
ax2.set_title('Auto-scaled Aspect')

ax3.imshow(grid, extent=[0,100,0,1], aspect=100)
ax3.set_title('Manually Set Aspect')

plt.tight_layout()
plt.show()

введіть тут опис зображення


Дякую. Кумедні документи нічого не говорять про scalarваріант. Здається, це масштабується y-axisза заданим скаляром.
orodbhen

@JoeKington чи можна отримати розмір окремих пікселів. Цей розмір залежить від розміру набору даних і може перетворити печворк плиток на суцільний сюжет, як у вашому випадку.
Олександр Цська

4

З plt.imshow()офіційного довідника ми знаємо, що аспект керує співвідношенням сторін осей. Ну, моїми словами, аспект - це точно співвідношення x одиниці та одиниці y . Більшу частину часу ми хочемо зберегти його як 1, оскільки ми не хочемо ненавмисно спотворювати цифри. Однак справді бувають випадки, коли нам потрібно вказати аспект значення, відмінне від 1. Допитуючий навів хороший приклад того, що вісь x та y можуть мати різні фізичні одиниці. Припустимо, що х - у км, а у - у м. Отже, для даних 10x10 масштаб повинен бути [0,10km, 0,10m] = [0, 10000m, 0, 10m]. У такому випадку, якщо ми продовжуємо використовувати за замовчуванням аспект = 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 так, щоб одиниця осі х в 1,5 рази перевищувала осі осі, що веде до квадратного кольорового пікселя та квадратної цілої фігури, але прямокутної піксельної одиниці. Очевидно, це зазвичай не приймається.

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)! Змінюйте аспект лише тоді, коли це необхідно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.