首页 文章

使用Matplotlib / Python绘制模糊的线条

提问于
浏览
0

我可以使用 Matplotlib 进行如下所示的可视化 .

enter image description here

另一种观点:

enter image description here

资料来源:http://dl.acm.org/citation.cfm?id=1961832

这些图像做了哪些以及我想要做的是组合两个可视化 . 一个(背景)是一个简单的绘图,可以用 imshowpcolorpcolormesh 完成,但另一个使用网格纹理,模糊( w 因子)决定了一些特征,在这种情况下,确定了不确定性 . 我不知道该怎么做是用不同的模糊绘制不同的线条 . 对于每个像素,我有一个不确定性,我应该在这个像素中画一条线,不确定性表示为线条模糊 .

我不知道如何用Matplotlib做后者(用模糊绘制线条) .

任何帮助,将不胜感激 . 先感谢您 .

1 回答

  • 6

    那么这就是我到目前为止所做的事情 - 我开始了一些切线复制 fig. 2 .

    明天会更新 . (上半部分只是为了创建一些数据)

    from mpl_toolkits.mplot3d import Axes3D
    from matplotlib import cm
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import proj3d
    import numpy as np
    import matplotlib.gridspec as gridspec
    import matplotlib
    
    def smooth1d(x, window_len):
        s=np.r_[2*x[0]-x[window_len:1:-1],x,2*x[-1]-x[-1:-window_len:-1]]
        w = np.hanning(window_len)
        y=np.convolve(w/w.sum(),s,mode='same')
        return y[window_len-1:-window_len+1]
    
    def smooth2d(A, sigma=3):
        window_len = max(int(sigma), 3)*2+1
        A1 = np.array([smooth1d(x, window_len) for x in np.asarray(A)])
        A2 = np.transpose(A1)
        A3 = np.array([smooth1d(x, window_len) for x in A2])
        A4 = np.transpose(A3)
    
        return A4
    
    class BaseFilter(object):
        def prepare_image(self, src_image, dpi, pad):
            ny, nx, depth = src_image.shape
            #tgt_image = np.zeros([pad*2+ny, pad*2+nx, depth], dtype="d")
            padded_src = np.zeros([pad*2+ny, pad*2+nx, depth], dtype="d")
            padded_src[pad:-pad, pad:-pad,:] = src_image[:,:,:]
    
            return padded_src#, tgt_image
    
        def get_pad(self, dpi):
            return 0
    
        def __call__(self, im, dpi):
            pad = self.get_pad(dpi)
            padded_src = self.prepare_image(im, dpi, pad)
            tgt_image = self.process_image(padded_src, dpi)
            return tgt_image, -pad, -pad
    
    class GaussianFilter(BaseFilter):
        "simple gauss filter"
        def __init__(self, sigma, alpha=0.5, color=None):
            self.sigma = sigma
            self.alpha = alpha
            if color is None:
                self.color=(0, 0, 0)
            else:
                self.color=color
    
        def get_pad(self, dpi):
            return int(self.sigma*3/72.*dpi)
    
    
        def process_image(self, padded_src, dpi):
            #offsetx, offsety = int(self.offsets[0]), int(self.offsets[1])
            tgt_image = np.zeros_like(padded_src)
            aa = smooth2d(padded_src[:,:,-1]*self.alpha,
                          self.sigma/72.*dpi)
            tgt_image[:,:,-1] = aa
            tgt_image[:,:,:-1] = self.color
            return tgt_image
    
    
    from matplotlib.artist import Artist
    
    class FilteredArtistList(Artist):
        """
        A simple container to draw filtered artist.
        """
        def __init__(self, artist_list, filter):
            self._artist_list = artist_list
            self._filter = filter
            Artist.__init__(self)
    
        def draw(self, renderer):
            renderer.start_rasterizing()
            renderer.start_filter()
            for a in self._artist_list:
                a.draw(renderer)
            renderer.stop_filter(self._filter)
            renderer.stop_rasterizing()
    
    
    
    
    
    ##Create the landscape
    from noise import snoise2
    
    def boxOnSurface(rect, X,Y,Z):
      #Make rectangle of indicies to draw. Left the four loops expanded for clarity. Otherwise it's fairly ugly.
      rXs, rYs, rZs = [],[],[]
    
      for j in range(rect[0][1], rect[1][1]):
        i = rect[0][0]
    
        rXs.append(X[i][j])
        rYs.append(Y[i][j])
        rZs.append(Z[i][j])
    
      for i in range(rect[0][0], rect[1][0]):
        j = rect[1][1]
    
        rXs.append(X[i][j])
        rYs.append(Y[i][j])
        rZs.append(Z[i][j])
    
      for j in range(rect[1][1], rect[0][1], -1):
        i = rect[1][0]
    
        rXs.append(X[i][j])
        rYs.append(Y[i][j])
        rZs.append(Z[i][j])
    
      for i in range(rect[1][0], rect[0][0]-1, -1):
        j = rect[0][1]
    
        rXs.append(X[i][j])
        rYs.append(Y[i][j])
        rZs.append(Z[i][j])
    
      return rXs, rYs, rZs, [np.mean(rXs), np.mean(rYs), np.mean(rZs)]
    
    
    
    octaves = 4
    freq = octaves * 100
    
    
    xs, ys = np.linspace(0.0, 100.0, 100), np.linspace(0.0, 100.0, 100)
    X,Y = np.meshgrid(xs,ys)
    
    Z1 = np.zeros(X.shape)
    
    
    for i,x in enumerate(xs):
      for j,y in enumerate(ys):
        Z1[i][j] = int(snoise2(x/freq, y/freq, octaves) * 127.0 + 128.0)
    
    
    
    # get some different colours for the surface.
    faceValues = np.zeros(X.shape)
    
    noise = []
    
    for i,x in enumerate(xs):
      for j,y in enumerate(ys):
        faceValues[i][j] = snoise2(4*x/freq, 4*y/freq, octaves)
    
    jet = cm.get_cmap("jet")
    faceColours = []
    
    
    for i,x in enumerate(xs):
      faceColours.append([])
      for j,y in enumerate(ys):
        normalised = (faceValues[i][j] - faceValues.min()) / (faceValues.max() - faceValues.min())
        faceColours[i].append(jet(normalised))
        faceValues[i][j] = normalised
    
    
    
    
    fig = plt.figure()
    miniPlotCount = 5
    gs = gridspec.GridSpec(5, miniPlotCount)
    ax = fig.add_subplot(gs[0:4,:], projection='3d')
    
    miniAxes = []
    for i in range(miniPlotCount):
      miniAxes.append(fig.add_subplot(gs[4,i]))
    
    ax.plot_surface(X,Y,Z1, cmap=cm.jet, linewidth=0.2, cstride=2, rstride=2, facecolors=faceColours, vmin=0, vmax=1)
    
    
    #This decides where we draw the rectangle to be inspecting.
    rect = ((25,45),(65,70))
    
    boxXs, boxYs, boxZs, middleOfBox = boxOnSurface(rect, X,Y,Z1)
    ax.plot(boxXs, boxYs, boxZs)
    
    xb, yb, zb = middleOfBox
    
    xPoint, yPoint, _ = proj3d.proj_transform(xb, yb, zb, ax.get_proj())
    
    
    labels = []
    grids = []
    for i in range(miniPlotCount):
      bbox = miniAxes[i].get_window_extent()
      xytext = ((bbox.min[0] + bbox.max[0])/2, (bbox.min[1] + bbox.max[1])/2)
      labels.append(ax.annotate("", xy=(xPoint,yPoint), arrowprops = {"arrowstyle":'->', "connectionstyle":'arc3,rad=0'}, textcoords="figure pixels", xytext=xytext))
    
    #  miniAxes[i].contourf(X[rect[0][0]:rect[1][0],rect[0][1]:rect[1][1]], Y[rect[0][0]:rect[1][0],rect[0][1]:rect[1][1]], Z1[rect[0][0]:rect[1][0],rect[0][1]:rect[1][1]])#, vmin=Z1.min(), vmax=Z1.max())
      miniAxes[i].contourf(X[rect[0][0]:rect[1][0],rect[0][1]:rect[1][1]], Y[rect[0][0]:rect[1][0],rect[0][1]:rect[1][1]], faceValues[rect[0][0]:rect[1][0],rect[0][1]:rect[1][1]], vmin=faceValues.min(), vmax=faceValues.max())
    
    # miniAxes[i].set_agg_filter(gaussFilter)
      gaussFilter = GaussianFilter(i)
      miniAxes[i].grid(linestyle="-", linewidth=2, agg_filter=gaussFilter)
    
    
    
    
    
    
    def update_position(e):
        xPoint, yPoint, _ = proj3d.proj_transform(xb, yb, zb, ax.get_proj())
        for label in labels:
          label.xy = xPoint, yPoint
          label.update_positions(fig.canvas.renderer)
        fig.canvas.draw()
    
    fig.canvas.mpl_connect('motion_notify_event', update_position)
    
    
    
    
    plt.show()
    

    这创造了这个:

    enter image description here

    这模糊了网格线 . (我不确定为什么它没有模糊其中的两个)看来你可以通过添加 agg_filter= kwarg来设置你在matplotlib中获得的任何对象的 agg_filter . 如果您编辑了 GaussianFilter 类,则可以使其接收所有不确定性数据,然后使用它来对图像的各个部分应用模糊/不透明/任何内容 .

相关问题