Интерактивная информация о пикселях изображения в Python?
Краткая версия: существует ли метод Python для отображения изображения, которое показывает в реальном времени индексы и интенсивности пикселей? Поэтому, когда я перемещаю курсор над изображением, у меня постоянно отображается дисплей, например pixel[103,214] = 198
(для оттенков серого) или pixel[103,214] = (138,24,211)
для rgb?
Длинная версия:
Предположим, что я открываю изображение в градациях серого, сохраненное как ndarray im
, и выводит его с помощью imshow
из matplotlib:
im = plt.imread('image.png')
plt.imshow(im,cm.gray)
Я получаю изображение, а в правом нижнем углу окна - интерактивное отображение индексов пикселей. Кроме того, что они не совсем, поскольку значения не являются целыми числами: x=134.64 y=129.169
например.
Если я настроил дисплей с правильным разрешением:
plt.axis('equal')
значения x и y по-прежнему не являются целыми числами.
Метод imshow
из пакета spectral
выполняет лучшую работу:
import spectral as spc
spc.imshow(im)
Затем в правом нижнем углу теперь есть pixel=[103,152]
.
Однако ни один из этих методов не показывает значения пикселей. Поэтому у меня есть два вопроса:
- Можно ли принудить
imshow
от matplotlib
(и imshow
от scikit-image
) показывать правильные (целочисленные) пиксельные индексы?
- Можно ли расширить любой из этих методов, чтобы показать значения пикселей?
Ответы
Ответ 1
Есть несколько разных способов сделать это.
Вы можете использовать обезьян-патч ax.format_coord
, аналогичный этот официальный пример. Я собираюсь использовать здесь немного более "пифонический" подход, который не полагается на глобальные переменные. (Обратите внимание, что я не предполагал, что extent
был указан kwarg, аналогичный примеру matplotlib. Чтобы быть полностью общим, вам нужно сделать прикосновение больше работы.)
import numpy as np
import matplotlib.pyplot as plt
class Formatter(object):
def __init__(self, im):
self.im = im
def __call__(self, x, y):
z = self.im.get_array()[int(y), int(x)]
return 'x={:.01f}, y={:.01f}, z={:.01f}'.format(x, y, z)
data = np.random.random((10,10))
fig, ax = plt.subplots()
im = ax.imshow(data, interpolation='none')
ax.format_coord = Formatter(im)
plt.show()
![enter image description here]()
В качестве альтернативы, чтобы подключить один из моих собственных проектов, вы можете использовать mpldatacursor
. Если вы укажете hover=True
, окно будет всплывать всякий раз, когда вы наводите курсор на активированного исполнителя. (По умолчанию он появляется только при нажатии.) Обратите внимание, что mpldatacursor
корректно обрабатывает extent
и origin
kwargs до imshow
.
import numpy as np
import matplotlib.pyplot as plt
import mpldatacursor
data = np.random.random((10,10))
fig, ax = plt.subplots()
ax.imshow(data, interpolation='none')
mpldatacursor.datacursor(hover=True, bbox=dict(alpha=1, fc='w'))
plt.show()
![enter image description here]()
Кроме того, я забыл упомянуть, как показывать индексы пикселей. В первом примере он просто предполагает, что i, j = int(y), int(x)
. Вы можете добавить их вместо x
и y
, если хотите.
С помощью mpldatacursor
вы можете указать их с помощью специального форматирования. Аргументы i
и j
являются правильными индексами пикселей, независимо от extent
и origin
изображенного графика.
Например (обратите внимание на отображение extent
изображения и отображаемых координат i,j
):
import numpy as np
import matplotlib.pyplot as plt
import mpldatacursor
data = np.random.random((10,10))
fig, ax = plt.subplots()
ax.imshow(data, interpolation='none', extent=[0, 1.5*np.pi, 0, np.pi])
mpldatacursor.datacursor(hover=True, bbox=dict(alpha=1, fc='w'),
formatter='i, j = {i}, {j}\nz = {z:.02g}'.format)
plt.show()
![enter image description here]()
Ответ 2
Абсолютный гоночный "однострочный" для этого: (не полагаясь на datacursor
)
def val_shower(im):
return lambda x,y: '%dx%d = %d' % (x,y,im[int(y+.5),int(x+.5)])
plt.imshow(image)
plt.gca().format_coord = val_shower(ims)
Он помещает изображение в закрытие, поэтому убедитесь, что у вас есть несколько изображений, каждый из которых отобразит свои собственные значения.
Ответ 3
Все примеры, которые я видел, работают только, если ваши x и y экстенты начинаются с 0. Вот код, который использует ваши экстенты изображения, чтобы найти значение z.
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
d = np.array([[i+j for i in range(-5, 6)] for j in range(-5, 6)])
im = ax.imshow(d)
im.set_extent((-5, 5, -5, 5))
def format_coord(x, y):
"""Format the x and y string display."""
imgs = ax.get_images()
if len(imgs) > 0:
for img in imgs:
try:
array = img.get_array()
extent = img.get_extent()
# Get the x and y index spacing
x_space = np.linspace(extent[0], extent[1], array.shape[1])
y_space = np.linspace(extent[3], extent[2], array.shape[0])
# Find the closest index
x_idx= (np.abs(x_space - x)).argmin()
y_idx= (np.abs(y_space - y)).argmin()
# Grab z
z = array[y_idx, x_idx]
return 'x={:1.4f}, y={:1.4f}, z={:1.4f}'.format(x, y, z)
except (TypeError, ValueError):
pass
return 'x={:1.4f}, y={:1.4f}, z={:1.4f}'.format(x, y, 0)
return 'x={:1.4f}, y={:1.4f}'.format(x, y)
# end format_coord
ax.format_coord = format_coord
Если вы используете PySide/PyQT, здесь приведен пример подсказки для мыши для данных
import matplotlib
matplotlib.use("Qt4Agg")
matplotlib.rcParams["backend.qt4"] = "PySide"
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
# Mouse tooltip
from PySide import QtGui, QtCore
mouse_tooltip = QtGui.QLabel()
mouse_tooltip.setFrameShape(QtGui.QFrame.StyledPanel)
mouse_tooltip.setWindowFlags(QtCore.Qt.ToolTip)
mouse_tooltip.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)
mouse_tooltip.show()
def show_tooltip(msg):
msg = msg.replace(', ', '\n')
mouse_tooltip.setText(msg)
pos = QtGui.QCursor.pos()
mouse_tooltip.move(pos.x()+20, pos.y()+15)
mouse_tooltip.adjustSize()
fig.canvas.toolbar.message.connect(show_tooltip)
# Show the plot
plt.show()
Ответ 4
с Jupyter вы можете сделать это либо с помощью datacursor(myax)
, либо ax.format_coord
.
Пример кода:
%matplotlib nbagg
import numpy as np
import matplotlib.pyplot as plt
X = 10*np.random.rand(5,3)
fig,ax = plt.subplots()
myax = ax.imshow(X, cmap=cm.jet,interpolation='nearest')
ax.set_title('hover over the image')
datacursor(myax)
plt.show()
datacursor(myax)
также можно заменить на ax.format_coord = lambda x,y : "x=%g y=%g" % (x, y)
Ответ 5
Для получения интерактивной информации о пикселях изображения используйте модуль imagetoolbox. Для загрузки модуля откройте командную строку и напишите
pip install imagetoolbox Введите данный код для получения интерактивной информации о пикселях изображения, введите описание изображения здесь. Вывод: введите описание изображения здесь.