【问题标题】:Slow Line2D rendering in matplotlibmatplotlib 中缓慢的 Line2D 渲染
【发布时间】:2012-01-30 08:35:43
【问题描述】:

我正在尝试使用 Line2D 在多边形上单击的最后一个点和用户鼠标之间呈现一条线。我当前的代码当前有效,但它在渲染之间永远滞后,因此该线落后于鼠标。当前相关代码为:

#in constructor 
cid2 = self.ui.canvas2.mpl_connect('motion_notify_event', self.renderMeasureLine)

#This gets called and is laggy
def renderMeasureLine(self, mouseEvent):            
    if self.measuring and mouseEvent.inaxes == self.ui.canvas2.axes and len(self.pointListX) > 0:

        if self.dotted_line in self.ui.canvas2.axes.lines:
            self.ui.canvas2.axes.lines.remove(self.dotted_line)
        self.dotted_line = Line2D([self.pointListX[-1],mouseEvent.xdata],[self.pointListY[-1],mouseEvent.ydata],
                                   color=color, axes=self.ui.canvas2.axes, ls = '--')
        self.ui.canvas2.axes.add_line(self.dotted_line)
        self.ui.canvas2.draw()

================================================ ===================================

#mpl canvas class
class MyDynamicMplCanvas(MyMplCanvas):
    """A canvas that updates itself every second with a new plot."""
    def __init__(self, *args, **kwargs):
        MyMplCanvas.__init__(self, *args, **kwargs)
        self.colorMap = cmap.bone

    def compute_initial_figure(self):
        self.axes.imshow(self.data, cmap = cmap.bone)

    def update_figure(self, dataOverride = None):
        if self.data is not None or dataOverride is not none:
            FigureCanvas.updateGeometry(self)
            self.axes.clear()
            if dataOverride is not None:
                self.axes.imshow(dataOverride, cmap = self.getColorMap())
            else:
                self.axes.imshow(self.data, cmap = self.getColorMap())
        self.draw()

所以本质上,每次鼠标移动时,我都想更新最后一次单击的多边形点和当前新鼠标位置之间的虚线。这行得通,但它是超级滞后。有什么想法吗??

编辑:正在发生的事情的图片。虚线是慢的。

【问题讨论】:

  • 使用 blitting,否则 matplotlib 将重绘整个图形只是为了更新行。 matplotlib 网站上有示例。否则,请仔细查看 matplotlib 源目录中游标类的源代码。
  • 啊,这就是我要找的,但找不到。有机会我会试一试的。

标签: python image matplotlib rendering


【解决方案1】:

不要为每次鼠标移动创建一个新的Line2DLine2D 可以有超过 2 个点。因此,改为使用Line2D.set_data() 更改单个Line2D 中的数据。

用几千个点画一个Line2D肯定比实例化和画几千个Line2Ds要快。

def renderMeasureLine(self, mouseEvent):            
    if (self.measuring and mouseEvent.inaxes == self.ui.canvas2.axes
            and len(self.pointListX) > 0):
        if self.dotted_line in self.ui.canvas2.axes.lines:
            x, y = self.dotted_line.get_data()
            x.append(mouseEvent.xdata)
            y.append(mouseEvent.ydata)
            self.dotted_line.set_data(x, y)
        else:
            self.dotted_line = Line2D(
                [self.pointListX[-1],mouseEvent.xdata],
                [self.pointListY[-1],mouseEvent.ydata],
                color=color, axes=self.ui.canvas2.axes, ls = '--')
            self.ui.canvas2.axes.add_line(self.dotted_line)

        self.ui.canvas2.blit(self.ui.canvas2.axes.bbox)
        self.ui.canvas2.draw_idle()

【讨论】:

  • 谢谢,这让我找到了解决方案,我花了最后一个小时试图找到一种方法,这样,如果鼠标移动并且没有在渲染计数上结束,它将画一条新线...无法用 matplotlib 或 qt 弄清楚(即使通过黑客攻击...)
  • 实际上,当您停止移动鼠标时,这也会变得不稳定和不正常:/ 也许使用 Line2D 并不是一个好的解决方案。
  • 也许,我们应该记住最后一条线的终点,而不是计算对renderMeasureLine的调用次数。然后计算该端点与新鼠标位置之间的距离。如果该距离大于dmin 且小于dmax,则画线。 dmin 将停止绘制非常短的线条,dmax 将停止绘制不规则的线条。
  • 啊,我会在今天晚些时候有机会时尝试一下,并告诉你它是否有效!好主意:)
  • 我认为tillsten 是对的——研究Cursor class 是如何做到的。除此之外,我在上面添加了一些代码来展示如何使用一个Line2D 而不是多个Line2Ds 来绘制整条线。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-06
  • 2017-01-30
  • 1970-01-01
  • 2021-06-04
  • 2017-09-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多