Python:鼠标单击坐标就像possib一样简单

2024-06-11 14:30:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我想编写一个交互式的Bezier曲线生成器,唯一的输入是图形上的鼠标单击坐标(使用matplotlib.pyplot)

因此,我想知道如何获得这些坐标,以及如何使用classself.functions尽可能简单地将它们堆叠到x轴和y轴的两个列表中。

谢谢你!

双模式


Tags: self图形列表matplotlib鼠标functions曲线class
1条回答
网友
1楼 · 发布于 2024-06-11 14:30:01

matplotlib中有一个event在单击绘图时返回鼠标坐标。检查以下配方:

import numpy as np
import matplotlib.pyplot as plt

class LineBuilder:
    def __init__(self, line,ax,color):
        self.line = line
        self.ax = ax
        self.color = color
        self.xs = []
        self.ys = []
        self.cid = line.figure.canvas.mpl_connect('button_press_event', self)
        self.counter = 0
        self.shape_counter = 0
        self.shape = {}
        self.precision = 10

    def __call__(self, event):
        if event.inaxes!=self.line.axes: return
        if self.counter == 0:
            self.xs.append(event.xdata)
            self.ys.append(event.ydata)
        if np.abs(event.xdata-self.xs[0])<=self.precision and np.abs(event.ydata-self.ys[0])<=self.precision and self.counter != 0:
            self.xs.append(self.xs[0])
            self.ys.append(self.ys[0])
            self.ax.scatter(self.xs,self.ys,s=120,color=self.color)
            self.ax.scatter(self.xs[0],self.ys[0],s=80,color='blue')
            self.ax.plot(self.xs,self.ys,color=self.color)
            self.line.figure.canvas.draw()
            self.shape[self.shape_counter] = [self.xs,self.ys]
            self.shape_counter = self.shape_counter + 1
            self.xs = []
            self.ys = []
            self.counter = 0
        else:
            if self.counter != 0:
                self.xs.append(event.xdata)
                self.ys.append(event.ydata)
            self.ax.scatter(self.xs,self.ys,s=120,color=self.color)
            self.ax.plot(self.xs,self.ys,color=self.color)
            self.line.figure.canvas.draw()
            self.counter = self.counter + 1

def create_shape_on_image(data,cmap='jet'):
    def change_shapes(shapes):
        new_shapes = {}
        for i in range(len(shapes)):
            l = len(shapes[i][1])
            new_shapes[i] = np.zeros((l,2),dtype='int')
            for j in range(l):
                new_shapes[i][j,0] = shapes[i][0][j]
                new_shapes[i][j,1] = shapes[i][1][j]
        return new_shapes
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.set_title('click to include shape markers (10 pixel precision to close the shape)')
    line = ax.imshow(data) 
    ax.set_xlim(0,data[:,:,0].shape[1])
    ax.set_ylim(0,data[:,:,0].shape[0])
    linebuilder = LineBuilder(line,ax,'red')
    plt.gca().invert_yaxis()
    plt.show()
    new_shapes = change_shapes(linebuilder.shape)
    return new_shapes

img = np.zeros((100,100,3),dtype='uint')
shapes = create_shape_on_image(img)[0]
print(shapes)

它有点广泛(您还可以查看matplotlib示例之一),但它允许您直观地看到单击的位置(您可以放置一个图像,而不是“黑色”numpy数组作为背景)。结果应该是这样的:

mouse click markers in matplotlib plot

最初它是为形状是封闭的,但适应您的需要。关闭绘图后,将有一个用于实际坐标的print

[[54 13]
 [19 39]
 [19 77]
 [58 78]
 [93 45]
 [90 11]
 [54 13]]

如果您希望以更温和的方式开始(一个简单的单击事件将坐标打印到控制台),请使用以下方法:

import matplotlib.pyplot as plt

def onclick(event):
    print(event.xdata, event.ydata)

fig,ax = plt.subplots()
ax.plot(range(10))
fig.canvas.mpl_connect('button_press_event', onclick)
plt.show()

相关问题 更多 >