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

Интерактивная информация о пикселях изображения в 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 от matplotlibimshow от scikit-image) показывать правильные (целочисленные) пиксельные индексы?
  • Можно ли расширить любой из этих методов, чтобы показать значения пикселей?
4b9b3361

Ответ 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 Введите данный код для получения интерактивной информации о пикселях изображения, введите описание изображения здесь. Вывод: введите описание изображения здесь.