matplotlib 用不同的颜色绘制许多不连续的线段

elcex8rz  于 2023-10-24  发布在  其他
关注(0)|答案(4)|浏览(99)

我有一组这样的数据记录:

  1. (s1, t1), (u1, v1), color1
  2. (s2, t2), (u2, v2), color2
  3. .
  4. .
  5. .
  6. (sN, tN), (uN, vN), colorN

在任何记录中,前两个值是线段的end-points,第三个值是该线段的color。更具体地说,(sn, tn)是第一个端点的x-y坐标,(un, vn)是第二个端点的x-y坐标。此外,color是带有alpha值的rgb。
一般来说,任何两条线段都是断开的(这意味着它们的端点不一定重合)。
如何使用matplotlib通过单个plot调用(或尽可能少的调用)绘制这些数据,因为可能有数千条记录。

尝试次数

在一个大列表中准备数据并对其调用plot太慢了。例如,以下代码无法在合理的时间内完成:

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. data = []
  4. for _ in xrange(60000):
  5. data.append((np.random.rand(), np.random.rand()))
  6. data.append((np.random.rand(), np.random.rand()))
  7. data.append('r')
  8. print 'now plotting...' # from now on, takes too long
  9. plt.plot(*data)
  10. print 'done'
  11. #plt.show()

我可以通过使用None插入技巧来加速绘图渲染,如下所示:

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from timeit import timeit
  4. N = 60000
  5. _s = np.random.rand(N)
  6. _t = np.random.rand(N)
  7. _u = np.random.rand(N)
  8. _v = np.random.rand(N)
  9. x = []
  10. y = []
  11. for s, t, u, v in zip(_s, _t, _u, _v):
  12. x.append(s)
  13. x.append(u)
  14. x.append(None)
  15. y.append(t)
  16. y.append(v)
  17. y.append(None)
  18. print timeit(lambda:plt.plot(x, y), number=1)

这在我的机器上执行不到一秒钟。我仍然要弄清楚如何嵌入颜色值(RGB与阿尔法通道)。

gcmastyq

gcmastyq1#

使用LineCollection

  1. import numpy as np
  2. import pylab as pl
  3. from matplotlib import collections as mc
  4. lines = [[(0, 1), (1, 1)], [(2, 3), (3, 3)], [(1, 2), (1, 3)]]
  5. c = np.array([(1, 0, 0, 1), (0, 1, 0, 1), (0, 0, 1, 1)])
  6. lc = mc.LineCollection(lines, colors=c, linewidths=2)
  7. fig, ax = pl.subplots()
  8. ax.add_collection(lc)
  9. ax.autoscale()
  10. ax.margins(0.1)

下面是输出:

展开查看全部
sulc1iza

sulc1iza2#

函数plot允许在一次调用中绘制多条线,如果你的数据只是在列表中,只要在传递给plot时解包即可:

  1. In [315]: data=[(1, 1), (2, 3), 'r', #assuming points are (1,2) (1,3) actually and,
  2. #here they are in form of (x1, x2), (y1, y2)
  3. ...: (2, 2), (4, 5), 'g',
  4. ...: (5, 5), (6, 7), 'b',]
  5. In [316]: plot(*data)
  6. Out[316]:
  7. [<matplotlib.lines.Line2D at 0x8752870>,
  8. <matplotlib.lines.Line2D at 0x8752a30>,
  9. <matplotlib.lines.Line2D at 0x8752db0>]

zfycwa2u

zfycwa2u3#

好吧,我最终在将PIL图像转换为numpy数组之前对PIL图像上的线条进行了光栅化:

  1. from PIL import Image
  2. from PIL import ImageDraw
  3. import random as rnd
  4. import numpy as np
  5. import matplotlib.pyplot as plt
  6. N = 60000
  7. s = (500, 500)
  8. im = Image.new('RGBA', s, (255,255,255,255))
  9. draw = ImageDraw.Draw(im)
  10. for i in range(N):
  11. x1 = rnd.random() * s[0]
  12. y1 = rnd.random() * s[1]
  13. x2 = rnd.random() * s[0]
  14. y2 = rnd.random() * s[1]
  15. alpha = rnd.random()
  16. color = (int(rnd.random() * 256), int(rnd.random() * 256), int(rnd.random() * 256), int(alpha * 256))
  17. draw.line(((x1,y1),(x2,y2)), fill=color, width=1)
  18. plt.imshow(np.asarray(im),
  19. origin='lower')
  20. plt.show()

这是目前为止最快的解决方案,它完全符合我的实时需求。

展开查看全部
1aaf6o9v

1aaf6o9v4#

我已经尝试了Python 3上可用的一些2D渲染引擎,同时在面向图像的深度学习和GAN中寻找输出阶段的快速解决方案。
使用以下基准:将99行渲染成256 x256离屏图像(或任何更有效的图像)的时间(有和没有抗锯齿)。
结果,在我的旧x301笔记本电脑的效率顺序:

  • PyGtk 2:~2500 FPS,(Python 2,GTK 2,不确定如何获得AA)
  • PyQt 5:~1200 FPS,~350(抗锯齿)
  • PyQt 4:约1100 FPS,约380(AA)
  • 开罗:~750 FPS,AA ~250(使用“FAST”AA仅略快)
  • PIL:~600 FPS

基线是一个循环,它花费约0.1 ms(10,000 FPS)检索随机数并调用原语。
PyGtk 2的基本代码:

  1. from gtk import gdk
  2. import random
  3. WIDTH = 256
  4. def r255(): return int(256.0*random.random())
  5. cmap = gdk.Colormap(gdk.visual_get_best_with_depth(24), True)
  6. black = cmap.alloc_color('black')
  7. white = cmap.alloc_color('white')
  8. pixmap = gdk.Pixmap(None, WIDTH, WIDTH, 24)
  9. pixmap.set_colormap(cmap)
  10. gc = pixmap.new_gc(black, line_width=2)
  11. pixmap.draw_rectangle(gc, True, -1, -1, WIDTH+2, WIDTH+2);
  12. gc.set_foreground(white)
  13. for n in range(99):
  14. pixmap.draw_line(gc, r255(), r255(), r255(), r255())
  15. gdk.Pixbuf(gdk.COLORSPACE_RGB, False, 8, WIDTH, WIDTH
  16. ).get_from_drawable(pixmap, cmap, 0,0, 0,0, WIDTH, WIDTH
  17. ).save('Gdk2-lines.png','png')

下面是PyQt 5的例子:

  1. from PyQt5.QtCore import Qt
  2. from PyQt5.QtGui import *
  3. import random
  4. WIDTH = 256.0
  5. def r255(): return WIDTH*random.random()
  6. image = QImage(WIDTH, WIDTH, QImage.Format_RGB16)
  7. painter = QPainter()
  8. image.fill(Qt.black)
  9. painter.begin(image)
  10. painter.setPen(QPen(Qt.white, 2))
  11. #painter.setRenderHint(QPainter.Antialiasing)
  12. for n in range(99):
  13. painter.drawLine(WIDTH*r0to1(),WIDTH*r0to1(),WIDTH*r0to1(),WIDTH*r0to1())
  14. painter.end()
  15. image.save('Qt5-lines.png', 'png')

下面是Python3-Cairo的完整性:

  1. import cairo
  2. from random import random as r0to1
  3. WIDTH, HEIGHT = 256, 256
  4. surface = cairo.ImageSurface(cairo.FORMAT_A8, WIDTH, HEIGHT)
  5. ctx = cairo.Context(surface)
  6. ctx.scale(WIDTH, HEIGHT) # Normalizing the canvas
  7. ctx.set_line_width(0.01)
  8. ctx.set_source_rgb(1.0, 1.0, 1.0)
  9. ctx.set_antialias(cairo.ANTIALIAS_NONE)
  10. #ctx.set_antialias(cairo.ANTIALIAS_FAST)
  11. ctx.set_operator(cairo.OPERATOR_CLEAR)
  12. ctx.paint()
  13. ctx.set_operator(cairo.OPERATOR_SOURCE)
  14. for n in range(99):
  15. ctx.move_to(r0to1(), r0to1())
  16. ctx.line_to(r0to1(), r0to1())
  17. ctx.stroke()
  18. surface.write_to_png('Cairo-lines.png')
展开查看全部

相关问题