matplotlib 图像的交互式像素信息

qvtsj1bj  于 2023-06-23  发布在  其他
关注(0)|答案(7)|浏览(181)

**简短版本:**是否有Python方法显示图像,真实的显示像素索引和强度?所以当我在图像上移动光标时,我有一个不断更新的显示,如pixel[103,214] = 198(用于灰度)或pixel[103,214] = (138,24,211)(用于rgb)?
长版本:

假设我打开一个保存为ndarray im的灰度图像,并从matplotlib中使用imshow显示它:

im = plt.imread('image.png')
plt.imshow(im,cm.gray)

我得到的是图像,在窗口框架的右下角,是像素索引的交互式显示。除了它们不完全一样,因为它们的值不是整数:例如x=134.64 y=129.169
如果我将显示器设置为正确的分辨率:

plt.axis('equal')

x和y值仍然不是整数。
spectral包中的imshow方法做得更好:

import spectral as spc
spc.imshow(im)

然后在右下角,我现在有pixel=[103,152]
然而,这些方法中没有一个也显示像素值。所以我有两个问题

  1. matplotlib中的imshow(以及scikit-image中的imshow)是否可以强制显示正确的(整数)像素索引?
    1.这些方法中的任何一个都可以扩展到显示像素值吗?
ddarikpa

ddarikpa1#

有几种不同的方法可以解决这个问题。
你可以用monkey-patch ax.format_coord,类似于this official example。我将在这里使用一种稍微更“pythonic”的方法,它不依赖于全局变量。(注意,我假设没有指定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()

或者,为了插入我自己的一个项目,可以使用mpldatacursor。如果指定hover=True,则每当您将鼠标悬停在启用的艺术家上方时,该框将弹出。(默认情况下,它只在点击时弹出。)注意mpldatacursor确实正确地处理extentorigin 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()

另外,我忘了提到如何显示像素索引。在第一个例子中,它只是假设i, j = int(y), int(x)。如果您愿意,可以添加它们来代替xy
使用mpldatacursor,您可以使用自定义格式化程序指定它们。ij参数是正确的像素索引,无论绘制的图像的extentorigin如何。
例如(注意图像的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()

3pmvbmvn

3pmvbmvn2#

一个绝对简单的“一行程序”来做到这一点:(不依赖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)

它会关闭图像,以便确保如果你有多个图像,每个图像都将显示自己的值。

mtb9vblg

mtb9vblg3#

我看到的所有例子都只在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()
5ktev3wc

5ktev3wc4#

在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)代替

2vuwiymt

2vuwiymt5#

如果你像我一样,在Google Colab上工作,这个解决方案不起作用,因为Colab禁用了matplotlib的图像交互功能。然后你可以简单地使用Plotly:https://plotly.com/python/imshow/

import plotly.express as px
import numpy as np
img_rgb = np.array([[[255, 0, 0], [0, 255, 0], [0, 0, 255]],
                [[0, 255, 0], [0, 0, 255], [255, 0, 0]]
               ], dtype=np.uint8)
fig = px.imshow(img_rgb)
fig.show()

kpbwa7wx

kpbwa7wx6#

Matplotlib具有内置的交互式绘图,它记录屏幕角落的像素值。
要安装,首先安装pip install ipympl
然后使用%matplotlib notebook%matplotlib widget而不是%matplotlib inline
plotlyBokeh的缺点是它们不能在Pycharm上工作。
有关详细信息,请查看doc

50pmv0ei

50pmv0ei7#

要获取图像的交互式像素信息,使用模块imagetToolbox下载模块打开命令提示符并写入
pip install imagetoolbox编写给定的代码以获取图像的交互式像素信息enter image description here输出:enter image description here

相关问题