【问题标题】:Matplotlib: draw a selection area in the shape of a rectangle with the mouseMatplotlib:用鼠标绘制矩形形状的选择区域
【发布时间】:2012-08-16 15:39:01
【问题描述】:

我希望能够通过鼠标事件在 matplotlib 图上绘制选择区域。我没有找到有关如何使用 python 执行此操作的信息。

最后,我希望能够在使用 matplotlib 底图创建的地图上用鼠标绘制感兴趣区域并检索角坐标。

有人有想法、例子、参考吗?

谢谢,

格雷格

class Annotate(object):
  def __init__(self):
      self.ax = plt.gca()
      self.rect = Rectangle((0,0), 1, 1, facecolor='None', edgecolor='green')
      self.x0 = None
      self.y0 = None
      self.x1 = None
      self.y1 = None
      self.ax.add_patch(self.rect)
      self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
      self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
      self.ax.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)
  def on_press(self, event):
      print 'press'
      self.x0 = event.xdata
      self.y0 = event.ydata    
      self.x1 = event.xdata
      self.y1 = event.ydata
      self.rect.set_width(self.x1 - self.x0)
      self.rect.set_height(self.y1 - self.y0)
      self.rect.set_xy((self.x0, self.y0))
      self.rect.set_linestyle('dashed')
      self.ax.figure.canvas.draw()
  def on_motion(self,event):
      if self.on_press is True:
          return
      self.x1 = event.xdata
      self.y1 = event.ydata
      self.rect.set_width(self.x1 - self.x0)
      self.rect.set_height(self.y1 - self.y0)
      self.rect.set_xy((self.x0, self.y0))
      self.rect.set_linestyle('dashed')
      self.ax.figure.canvas.draw()
  def on_release(self, event):
      print 'release'
      self.x1 = event.xdata
      self.y1 = event.ydata
      self.rect.set_width(self.x1 - self.x0)
      self.rect.set_height(self.y1 - self.y0)
      self.rect.set_xy((self.x0, self.y0))
      self.rect.set_linestyle('solid')
      self.ax.figure.canvas.draw()
      print self.x0,self.x1,self.y0,self.y1
      return [self.x0,self.x1,self.y0,self.y1]

【问题讨论】:

    标签: python matplotlib mouse selection matplotlib-basemap


    【解决方案1】:

    这是一个小例子,展示了如何使用鼠标在 matplotlib 图上绘制一个矩形。

    import matplotlib.pyplot as plt
    from matplotlib.patches import Rectangle
    
    class Annotate(object):
        def __init__(self):
            self.ax = plt.gca()
            self.rect = Rectangle((0,0), 1, 1)
            self.x0 = None
            self.y0 = None
            self.x1 = None
            self.y1 = None
            self.ax.add_patch(self.rect)
            self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
            self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
    
        def on_press(self, event):
            print 'press'
            self.x0 = event.xdata
            self.y0 = event.ydata
    
        def on_release(self, event):
            print 'release'
            self.x1 = event.xdata
            self.y1 = event.ydata
            self.rect.set_width(self.x1 - self.x0)
            self.rect.set_height(self.y1 - self.y0)
            self.rect.set_xy((self.x0, self.y0))
            self.ax.figure.canvas.draw()
    
    a = Annotate()
    plt.show()
    

    【讨论】:

    • 谢谢,这正是我想要的!你知道我可以做些什么来显示在 on_press 事件期间绘制的矩形吗?是否也可以将颜色设置为透明浅灰色?非常感谢
    • 如果你想在移动鼠标时更新绘图,你想添加行self.ax.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)并定义一个方法on_motion来做你想做的事。见matplotlib.sourceforge.net/examples/event_handling/index.html。要查看您可以编辑哪些矩形属性,请参阅matplotlib.sourceforge.net/api/…
    • 我几乎成功了!但我仍然有一个问题:矩形是在移动时绘制的,但我希望它在 on_press+on_motion 事件期间绘制。在原始问题中查看我的新代码。谢谢。
    • 在 on_press 中将布尔 is_pressed 属性设置为 true,在 on_release 中将其设置为 false,并且仅在 self.is_pressed == True 时绘制矩形(请注意您的测试是否 self.on_press 不感觉,因为你在测试一个方法是否为真)
    • @ChrisB,感谢您的回答,mpl_connect 机制对我来说更加清晰。
    【解决方案2】:

    Matplotlib 提供了自己的RectangleSelector。 matplotlib 页面上有an example,您可以根据自己的需要进行调整。

    简化版如下所示:

    import matplotlib.pyplot as plt
    import numpy as np
    from matplotlib.widgets  import RectangleSelector
    
    xdata = np.linspace(0,9*np.pi, num=301)
    ydata = np.sin(xdata)
    
    fig, ax = plt.subplots()
    line, = ax.plot(xdata, ydata)
    
    
    def line_select_callback(eclick, erelease):
        x1, y1 = eclick.xdata, eclick.ydata
        x2, y2 = erelease.xdata, erelease.ydata
    
        rect = plt.Rectangle( (min(x1,x2),min(y1,y2)), np.abs(x1-x2), np.abs(y1-y2) )
        ax.add_patch(rect)
    
    
    rs = RectangleSelector(ax, line_select_callback,
                           drawtype='box', useblit=False, button=[1], 
                           minspanx=5, minspany=5, spancoords='pixels', 
                           interactive=True)
    
    plt.show()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-20
      相关资源
      最近更新 更多