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

Ala*_*air 24 python image image-processing matplotlib scikit-image

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

长版:

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

im = plt.imread('image.png')
plt.imshow(im,cm.gray)
Run Code Online (Sandbox Code Playgroud)

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

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

plt.axis('equal')
Run Code Online (Sandbox Code Playgroud)

x和y值仍然不是整数.

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

import spectral as spc
spc.imshow(im)
Run Code Online (Sandbox Code Playgroud)

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

但是,这些方法都没有显示像素值.所以我有两个问题:

  1. 可以强制imshowfrom matplotlib(和imshowfrom scikit-image)显示正确的(整数)像素索引吗?
  2. 可以扩展这些方法中的任何一个以显示像素值吗?

Joe*_*ton 41

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

你可以使用猴子补丁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()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

或者,只需插入我自己的一个项目,就可以使用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()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

另外,我忘了提到如何显示像素索引.在第一个例子中,它只是假设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()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 请注意,第一个示例不正确半个像素.它应该是`z = self.im.get_array()[int(y + 0.5),int(x + 0.5)]`. (2认同)

Roy*_*rot 5

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

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