ショートバージョン: 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つの質問があります。
imshow
からのmatplotlib
(および_scikit-image
_からのimshow
)は、正しい(整数)ピクセルインデックスを表示するように強制できますか?これについては、いくつかの異なる方法があります。
この公式の例 と同様に、_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()
_
あるいは、自分のプロジェクトの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()
_
また、ピクセルインデックスの表示方法について言及するのを忘れました。最初の例では、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()
_
これを行うための絶対的な最低限の「ワンライナー」:(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)
画像を閉じますので、複数の画像がある場合、それぞれに独自の値が表示されるようにします。
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)
に置き換えることもできます
私が見たすべての例は、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()