问题
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?
Long version:
Suppose I open a grayscale image saved as an ndarray im
and display it with imshow
from 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.169
for example.
If I set the display with correct resolution:
plt.axis(\'equal\')
the x and y values are still not integers.
The imshow
method from the spectral
package does a better job:
import spectral as spc
spc.imshow(im)
Then in the bottom right I now have pixel=[103,152]
for example.
However, none of these methods also shows the pixel values. So I have two questions:
- Can the
imshow
frommatplotlib
(and theimshow
fromscikit-image
) be coerced into showing the correct (integer) pixel indices? - Can any of these methods be extended to show the pixel values as well?
回答1:
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 extent
kwarg was specified, similar to the matplotlib example. To be fully general, you need to do a touch more work.)
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()

Alternatively, just to plug one of my own projects, you can use mpldatacursor for 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 mpldatacursor
does handle the extent
and origin
kwargs to imshow
correctly.
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()

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 x
and y
, if you'd prefer.
With mpldatacursor
, you can specify them with a custom formatter. The i
and j
arguments are the correct pixel indices, regardless of the extent
and origin
of the image plotted.
For example (note the extent
of the image vs. the i,j
coordinates displayed):
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()

回答2:
An absolute bare-bones "one-liner" to do this: (without relying on 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.
回答3:
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.
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
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:
with Jupyter you can do so either with datacursor(myax)
or by 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)
回答5:
To get interactive pixel information of an image use the module imagetoolbox To download the module open the command prompt and write
pip install imagetoolbox Write the given code to get interactive pixel information of an image enter image description here Output:enter image description here
来源:https://stackoverflow.com/questions/27704490/interactive-pixel-information-of-an-image-in-python