gpt4 book ai didi

python - Matplotlib:更新图形后交互式缩放工具中的错误

转载 作者:太空宇宙 更新时间:2023-11-03 20:40:33 32 4
gpt4 key购买 nike

我再次陷入了使用 matplotlib 进行交互式绘图的困境。

其他一切都像一个魅力(悬停和单击图中的对象),但如果我缩放显示的图形并且它将更新,则缩放矩形将保留在新图形中。也许我必须以某种方式重置缩放设置,但我无法从其他 StackOverflow 问题中找到正确的方法(清除数字显然还不够)。

我构建了一个玩具示例来说明问题。四个点附加到四个图像,并将它们绘制到图中。在交互模式下,通过将光标插入所选点的顶部,它会在图像框中显示相关图像。单击一点后,程序等待 2 秒,然后通过将所有样本旋转 15 度来更新 View 。

当前 View 缩放然后更新时会出现此问题。缩放到矩形将自动启动,在图形中的任意位置单击一次后,矩形就会消失,而不执行任何操作。如下图所示。我只想在图形更新后有正常的光标。

enter image description here

以下是玩具示例的代码:

import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
import numpy as np
import copy

def initialize_figure(fignum):
plt.figure(fignum)
plt.clf()

def draw_interactive_figures(new_samples, images):
global new_samples_tmp, images_tmp, offset_image_tmp, image_box_tmp, fig_tmp, x_tmp, y_tmp
initialize_figure(1)
plt.ion()
fig_tmp = plt.gcf()
images_tmp = copy.deepcopy(images)
offset_image_tmp = OffsetImage(images_tmp[0,:,:,:])
image_box_tmp = (40., 40.)
x_tmp = new_samples[:,0]
y_tmp = new_samples[:,1]
new_samples_tmp = copy.deepcopy(new_samples)
update_plot()

fig_tmp.canvas.mpl_connect('motion_notify_event', hover)
fig_tmp.canvas.mpl_connect('button_press_event', click)
plt.show()
fig_tmp.canvas.start_event_loop()
plt.ioff()

def update_plot():
global points_tmp, annotationbox_tmp
ax = plt.gca()
points_tmp = plt.scatter(*new_samples_tmp.T, s=14, c='b', edgecolor='k')
annotationbox_tmp = AnnotationBbox(offset_image_tmp, (0,0), xybox=image_box_tmp, xycoords='data', boxcoords='offset points', pad=0.3, arrowprops=dict(arrowstyle='->'))
ax.add_artist(annotationbox_tmp)
annotationbox_tmp.set_visible(False)

def hover(event):
if points_tmp.contains(event)[0]:
inds = points_tmp.contains(event)[1]['ind']
ind = inds[0]
w,h = fig_tmp.get_size_inches()*fig_tmp.dpi
ws = (event.x > w/2.)*-1 + (event.x <= w/2.)
hs = (event.y > h/2.)*-1 + (event.y <= h/2.)
annotationbox_tmp.xybox = (image_box_tmp[0]*ws, image_box_tmp[1]*hs)
annotationbox_tmp.set_visible(True)
annotationbox_tmp.xy =(x_tmp[ind], y_tmp[ind])
offset_image_tmp.set_data(images_tmp[ind,:,:])
else:
annotationbox_tmp.set_visible(False)
fig_tmp.canvas.draw_idle()

def click(event):
if points_tmp.contains(event)[0]:
inds = points_tmp.contains(event)[1]['ind']
ind = inds[0]
initialize_figure(1)
update_plot()
plt.scatter(x_tmp[ind], y_tmp[ind], s=20, marker='*', c='y')
plt.pause(2)
fig_tmp.canvas.stop_event_loop()
fig_tmp.canvas.draw_idle()

def main():
fig, ax = plt.subplots(1, figsize=(7, 7))

points = np.array([[1,1],[1,-1],[-1,1],[-1,-1]])
zero_layer = np.zeros([28,28])
one_layer = np.ones([28,28])*255
images = np.array([np.array([zero_layer, zero_layer, one_layer]).astype(np.uint8),np.array([zero_layer, one_layer, zero_layer]).astype(np.uint8),np.array([one_layer, zero_layer, zero_layer]).astype(np.uint8),np.array([one_layer, zero_layer, one_layer]).astype(np.uint8)])
images = np.transpose(images, (0,3,2,1))
theta = 0
delta = 15 * (np.pi/180)
rotation_matrix = np.array([[np.cos(theta),-np.sin(theta)],[np.sin(theta),np.cos(theta)]])
while True:
rotated_points = np.matmul(points, rotation_matrix)
draw_interactive_figures(rotated_points, images)
theta += delta
rotation_matrix = np.array([[np.cos(theta),-np.sin(theta)],[np.sin(theta),np.cos(theta)]])

if __name__== "__main__":
main()

提前致谢!

最佳答案

我在这里为您提供一个起点。以下是一个创建绘图并允许您通过单击轴添加新点的脚本。对于每个点,可以将鼠标悬停并显示相应的图像。

import matplotlib.pyplot as plt
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
import numpy as np


class MyInteractivePlotter():
def __init__(self):
self.fig, self.ax = plt.subplots()
self.ax.set(xlim=(0,1), ylim=(0,1))

self.points = np.array([[0.5,0.5]]) # will become N x 2 array
self.images = [np.random.rand(10,10)]

self.scatter = self.ax.scatter(*self.points.T)
self.im = OffsetImage(self.images[0], zoom=5)

self.ab = AnnotationBbox(self.im, (0,0), xybox=(50., 50.), xycoords='data',
boxcoords="offset points", pad=0.3,
arrowprops=dict(arrowstyle="->"))
# add it to the axes and make it invisible
self.ax.add_artist(self.ab)
self.ab.set_visible(False)

self.cid = self.fig.canvas.mpl_connect("button_press_event", self.onclick)
self.hid = self.fig.canvas.mpl_connect("motion_notify_event", self.onhover)

def add_point(self):
# Update points (here, we just add a new random point)
self.points = np.concatenate((self.points, np.random.rand(1,2)), axis=0)
# For each points there is an image. (Here, we just add a random one)
self.images.append(np.random.rand(10,10))
# Update the scatter plot to show the new point
self.scatter.set_offsets(self.points)


def onclick(self, event):
self.add_point()
self.fig.canvas.draw_idle()

def onhover(self, event):
# if the mouse is over the scatter points
if self.scatter.contains(event)[0]:
# find out the index within the array from the event
ind, = self.scatter.contains(event)[1]["ind"]
# make annotation box visible
self.ab.set_visible(True)
# place it at the position of the hovered scatter point
self.ab.xy = self.points[ind,:]
# set the image corresponding to that point
self.im.set_data(self.images[ind])
else:
#if the mouse is not over a scatter point
self.ab.set_visible(False)
self.fig.canvas.draw_idle()


m = MyInteractivePlotter()
plt.show()

我建议您采用这个并将您的功能添加到其中。一旦您偶然发现问题,您可以用它来寻求澄清。

关于python - Matplotlib:更新图形后交互式缩放工具中的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56888363/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com