栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Python中的交互式BSpline拟合

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python中的交互式BSpline拟合

当然,您需要将功能添加到中

PolygonInteractor
。但是不要让它自己绘制任何东西。然后在类中添加新行,
self.line2
这将是要更新的行。

最后,让全班同学也为您画一条新线。并使用插值函数的结果更新它。

为了方便起见,您可以将“多边形(

self.poly
)”设置为不可见,也可以从中删除该线,
self.line
并且仅显示点可能有意义。

import numpy as npfrom  scipy.interpolate import interp1dfrom matplotlib.lines import Line2Dfrom matplotlib.artist import Artistfrom matplotlib.mlab import dist_point_to_segmentclass PolygonInteractor(object):    """    A polygon editor.    https://matplotlib.org/gallery/event_handling/poly_editor.html    Key-bindings      't' toggle vertex markers on and off.  When vertex markers are on,          you can move them, delete them      'd' delete the vertex under point      'i' insert a vertex at point.  You must be within epsilon of the          line connecting two existing vertices    """    showverts = True    epsilon = 5  # max pixel distance to count as a vertex hit    def __init__(self, ax, poly, visible=False):        if poly.figure is None: raise RuntimeError('You must first add the polygon to a figure '         'or canvas before defining the interactor')        self.ax = ax        canvas = poly.figure.canvas        self.poly = poly        self.poly.set_visible(visible)        x, y = zip(*self.poly.xy)        self.line = Line2D(x, y, ls="",     marker='o', markerfacecolor='r',     animated=True)        self.ax.add_line(self.line)        self.cid = self.poly.add_callback(self.poly_changed)        self._ind = None  # the active vert        canvas.mpl_connect('draw_event', self.draw_callback)        canvas.mpl_connect('button_press_event', self.button_press_callback)        canvas.mpl_connect('key_press_event', self.key_press_callback)        canvas.mpl_connect('button_release_event', self.button_release_callback)        canvas.mpl_connect('motion_notify_event', self.motion_notify_callback)        self.canvas = canvas        x,y = self.interpolate()        self.line2 = Line2D(x, y, animated=True)        self.ax.add_line(self.line2)    def interpolate(self):        x, y = self.poly.xy[:].T        i = np.arange(len(x))        interp_i = np.linspace(0, i.max(), 100 * i.max())        xi = interp1d(i, x, kind='cubic')(interp_i)          yi = interp1d(i, y, kind='cubic')(interp_i)        return xi,yi    def draw_callback(self, event):        self.background = self.canvas.copy_from_bbox(self.ax.bbox)        self.ax.draw_artist(self.poly)        self.ax.draw_artist(self.line)        self.ax.draw_artist(self.line2)        # do not need to blit here, this will fire before the screen is        # updated    def poly_changed(self, poly):        'this method is called whenever the polygon object is called'        # only copy the artist props to the line (except visibility)        vis = self.line.get_visible()        Artist.update_from(self.line, poly)        self.line.set_visible(vis)  # don't use the poly visibility state    def get_ind_under_point(self, event):        'get the index of the vertex under point if within epsilon tolerance'        # display coords        xy = np.asarray(self.poly.xy)        xyt = self.poly.get_transform().transform(xy)        xt, yt = xyt[:, 0], xyt[:, 1]        d = np.hypot(xt - event.x, yt - event.y)        indseq, = np.nonzero(d == d.min())        ind = indseq[0]        if d[ind] >= self.epsilon: ind = None        return ind    def button_press_callback(self, event):        'whenever a mouse button is pressed'        if not self.showverts: return        if event.inaxes is None: return        if event.button != 1: return        self._ind = self.get_ind_under_point(event)    def button_release_callback(self, event):        'whenever a mouse button is released'        if not self.showverts: return        if event.button != 1: return        self._ind = None    def key_press_callback(self, event):        'whenever a key is pressed'        if not event.inaxes: return        if event.key == 't': self.showverts = not self.showverts self.line.set_visible(self.showverts) if not self.showverts:     self._ind = None        elif event.key == 'd': ind = self.get_ind_under_point(event) if ind is not None:     self.poly.xy = np.delete(self.poly.xy,        ind, axis=0)     self.line.set_data(zip(*self.poly.xy))        elif event.key == 'i': xys = self.poly.get_transform().transform(self.poly.xy) p = event.x, event.y  # display coords for i in range(len(xys) - 1):     s0 = xys[i]     s1 = xys[i + 1]     d = dist_point_to_segment(p, s0, s1)     if d <= self.epsilon:         self.poly.xy = np.insert(  self.poly.xy, i+1,  [event.xdata, event.ydata],  axis=0)         self.line.set_data(zip(*self.poly.xy))         break        if self.line.stale: self.canvas.draw_idle()    def motion_notify_callback(self, event):        'on mouse movement'        if not self.showverts: return        if self._ind is None: return        if event.inaxes is None: return        if event.button != 1: return        x, y = event.xdata, event.ydata        self.poly.xy[self._ind] = x, y        if self._ind == 0: self.poly.xy[-1] = x, y        elif self._ind == len(self.poly.xy) - 1: self.poly.xy[0] = x, y        self.line.set_data(zip(*self.poly.xy))        x,y = self.interpolate()        self.line2.set_data(x,y)        self.canvas.restore_region(self.background)        self.ax.draw_artist(self.poly)        self.ax.draw_artist(self.line)        self.ax.draw_artist(self.line2)        self.canvas.blit(self.ax.bbox)if __name__ == '__main__':    import matplotlib.pyplot as plt    from matplotlib.patches import Polygon    #theta = np.arange(0, 2*np.pi, 0.1)    #r = 1.5    #xs = r*np.cos(theta)    #ys = r*np.sin(theta)    xs = (921, 951, 993, 1035, 1065, 1045, 993, 945)    ys = (1181, 1230, 1243, 1230, 1181, 1130, 1130, 1130)    poly = Polygon(list(zip(xs, ys)), animated=True)    fig, ax = plt.subplots()    ax.add_patch(poly)    p = PolygonInteractor(ax, poly, visible=False)    ax.set_title('Click and drag a point to move it')    ax.set_xlim((800, 1300))    ax.set_ylim((1000, 1300))    plt.show()

请注意,此处创建的曲线不是真正的循环。它有一个起点,曲线并不真正平滑。可以通过使用贝塞尔曲线的真循环集来避免这种情况,如使用matplotlib创建随机形状/轮廓所示。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/625878.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号