web-dev-qa-db-ja.com

Pythonの画像のインタラクティブなピクセル情報?

ショートバージョン: Pythonピクセルインデックスと強度をリアルタイムで表示する画像を表示する方法はありますか?イメージ、_pixel[103,214] = 198_(グレースケール用)またはrgbのpixel[103,214] = (138,24,211)などの表示が継続的に更新されていますか?

長いバージョン:

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の値はまだ整数ではありません。

imshowパッケージのspectralメソッドはより良い仕事をします:

_import spectral as spc
spc.imshow(im)
_

次に、右下に、たとえば_pixel=[103,152]_があります。

ただし、これらのメソッドはいずれもピクセル値を表示しません。そこで、2つの質問があります。

  1. imshowからのmatplotlib(および_scikit-image_からのimshow)は、正しい(整数)ピクセルインデックスを表示するように強制できますか?
  2. これらのメソッドのいずれかを拡張して、ピクセル値も表示できますか?
24
Alasdair

これについては、いくつかの異なる方法があります。

この公式の例 と同様に、_ax.format_coord_をモンキーパッチできます。ここでは、グローバル変数に依存しない、もう少し「Python的な」アプローチを使用します。 (matplotlibの例と同様に、extent kwargが指定されていないと仮定していることに注意してください。完全に一般化するには、 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()
_

enter image description here

あるいは、自分のプロジェクトの1つをプラグインするために、 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

40
Joe Kington

これを行うための絶対的な最低限の「ワンライナー」:(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)

画像を閉じますので、複数の画像がある場合、それぞれに独自の値が表示されるようにします。

2
Roy Shilkrot

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)に置き換えることもできます

0
shahar_m

私が見たすべての例は、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()
0
justengel