Python中图像的交互式像素信息?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27704490/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 02:09:23  来源:igfitidea点击:

Interactive pixel information of an image in Python?

pythonimageimage-processingmatplotlibscikit-image

提问by Alasdair

Short version:is there a Python method for displaying an image which shows, in real time, the pixel indices and intensities? So that as I move the cursor over the image, I have a continually updated display such as pixel[103,214] = 198(for grayscale) or pixel[103,214] = (138,24,211)for rgb?

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

Long version:

长版:

Suppose I open a grayscale image saved as an ndarray imand display it with imshowfrom matplotlib:

假设我打开一个保存为 ndarray 的灰度图像imimshow从 matplotlib 中显示它:

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

What I get is the image, and in the bottom right of the window frame, an interactive display of the pixel indices. Except that they're not quite, as the values are not integers: x=134.64 y=129.169for example.

我得到的是图像,在窗口框架的右下角,是像素索引的交互式显示。除了它们不完全是,因为值不是整数:x=134.64 y=129.169例如。

If I set the display with correct resolution:

如果我用正确的分辨率设置显示器:

plt.axis('equal')

the x and y values are still not integers.

x 和 y 值仍然不是整数。

The imshowmethod from the spectralpackage does a better job:

imshow从方法spectral包做一个更好的工作:

import spectral as spc
spc.imshow(im)

Then in the bottom right I now have pixel=[103,152]for example.

然后在右下角我现在有pixel=[103,152]例如。

However, none of these methods also shows the pixel values. So I have two questions:

然而,这些方法都没有显示像素值。所以我有两个问题:

  1. Can the imshowfrom matplotlib(and the imshowfrom scikit-image) be coerced into showing the correct (integer) pixel indices?
  2. Can any of these methods be extended to show the pixel values as well?
  1. 可以imshowmatplotlib(和imshowscikit-image)被强迫显示正确的(整数)像素的指数?
  2. 这些方法中的任何一种都可以扩展以显示像素值吗?

回答by Joe Kington

There a couple of different ways to go about this.

有几种不同的方法可以解决这个问题。

You can monkey-patch ax.format_coord, similar to this official example. I'm going to use a slightly more "pythonic" approach here that doesn't rely on global variables. (Note that I'm assuming no extentkwarg was specified, similar to the matplotlib example. To be fully general, you need to do a touch more work.)

您可以使用monkey-patch ax.format_coord,类似于这个官方示例。我将在这里使用一种稍微更“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()

enter image description here

在此处输入图片说明

Alternatively, just to plug one of my own projects, you can use mpldatacursorfor this. If you specify hover=True, the box will pop up whenever you hover over an enabled artist. (By default it only pops up when clicked.) Note that mpldatacursordoes handle the extentand originkwargs to imshowcorrectly.

或者,只是插入我自己的项目之一,您可以使用mpldatacursor它。如果您指定hover=True,则只要您将鼠标悬停在启用的艺术家上,就会弹出该框。(默认情况下,它仅在单击时弹出。)请注意,mpldatacursor确实可以正确处理extentoriginkwargs 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

在此处输入图片说明

Also, I forgot to mention how to show the pixel indices. In the first example, it's just assuming that i, j = int(y), int(x). You can add those in place of xand y, if you'd prefer.

另外,我忘了提及如何显示像素索引。在第一个示例中,它只是假设i, j = int(y), int(x). 如果您愿意,可以添加这些来代替xy

With mpldatacursor, you can specify them with a custom formatter. The iand jarguments are the correct pixel indices, regardless of the extentand originof the image plotted.

使用mpldatacursor,您可以使用自定义格式化程序指定它们。在ij参数是正确的像素指标,不管extentorigin图像的绘制。

For example (note the extentof the image vs. the i,jcoordinates displayed):

例如(注意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

在此处输入图片说明

回答by justengel

All of the examples that I have seen only work if your x and y extents start from 0. Here is code that uses your image extents to find the z value.

我看到的所有示例仅在您的 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

If you are using PySide/PyQT here is an example to have a mouse hover tooltip for the data

如果您使用的是 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()

回答by shahar_m

with Jupyter you can do so either with datacursor(myax)or by ax.format_coord.

使用 Jupyter,您可以使用datacursor(myax)或通过ax.format_coord.

Sample code:

示例代码:

%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()

the datacursor(myax)can also be replaced with ax.format_coord = lambda x,y : "x=%g y=%g" % (x, y)

datacursor(myax)也被替换ax.format_coord = lambda x,y : "x=%g y=%g" % (x, y)

回答by Roy Shilkrot

An absolute bare-bones "one-liner" to do this: (without relying on datacursor)

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

It puts the image in closure so makes sure if you have multiple images each will display its own values.

它将图像置于封闭状态,因此请确保您有多个图像,每个图像都将显示自己的值。

回答by Debangshu Chakraborty

To get interactive pixel information of an image use the module imagetoolbox To download the module open the command prompt and write

要获取图像的交互式像素信息,请使用模块 imagetoolbox 要下载模块,请打开命令提示符并写入

pip install imagetoolbox Write the given code to get interactive pixel information of an image enter image description hereOutput:enter image description here

pip install imagetoolbox 编写给定代码以获取图像的交互式像素信息在 此处输入图像描述输出:在此处输入图像描述