matplotlib从起点出发(15)_Tutorial_15_blitting

2024-04-22 08:12

本文主要是介绍matplotlib从起点出发(15)_Tutorial_15_blitting,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

0 位图传输技术与快速渲染

Blitting,即位图传输、块传输技术是栅格图形化中的标准技术。在Matplotlib的上下文中,该技术可用于(大幅度)提高交互式图形的性能。例如,动画和小部件模块在内部使用位图传输。在这里,我们将演示如何在这些类之外实现自己的blitting。

位图传输技术通过将所有不变的图形元素渲染到背景图像中来加速重复绘图。然后,对于每次绘图,只需要将不断变化的元素绘制到此背景上。例如,如果一个Axes的限制没有改变,我们可以渲染一次空轴,包括所有刻度和标签,然后只绘制变化的数据。

这种策略是:

  • 准备常量背景:
    • 绘制图形,但通过将所有要动画化的artists对象标记为动画来排除它们(参看Artist.set_animated);
    • 保存一份RBGA缓存的备份。
  • 渲染单个图像:
    • 还原RBGA缓冲区的副本;
    • 使用Axes.draw_artist/Figure.draw_artist重新绘制动画Artist;
    • 在屏幕上显示生成的图像。

此过程的一个结果是,你的动态artists始终绘制在静态artists之上。

并非所有的后端都支持传输。你可以通过以下的方式检查给定的画布是否支持这样做:FigureCanvasBase.supports_blit属性。

警告
此代码不适用于OSX后端(但适用于Mac上的其他GUI后端)。

1 最小示例

我们可以将FigureCanvasAgg方法copy_from_bboxrestore_region结合在artists上设置animated=True来实现一个使用位图传输来加速渲染的最小示例。

import matplotlib.pyplot as plt
import numpy as npx = np.linspace(0, 2 * np.pi, 100)fig, ax = plt.subplots()# animated=True 告诉 matplotlib 只在我们显式请求时才绘制
# 某个artist
(ln,) = ax.plot(x, np.sin(x), animated=True)# 确保窗口已经显示,但脚本继续运行
plt.show(block=False)# 停止欣赏空荡荡的窗口,确保至少渲染一次
#
# 我们需要在屏幕上完整绘制这个图形直到最终的大小
# 在我们继续之前 :
#  a) 我们有正确的大小和绘制的背景可以抓取
#  b) 我们可以渲染缓存,从而 ``ax.draw_artist`` 可以工作
# 所以我们旋转事件循环,让后端处理任何待处理的操作
plt.pause(0.1)# 获取整张图像的副本(所有fig.bbox中的内容)
bg = fig.canvas.copy_from_bbox(fig.bbox)
# 绘制动画artist, 这里使用了一个缓存渲染
ax.draw_artist(ln)
# 将结果显示到屏幕上,这将RGBA缓存更新从渲染器中推送到GUI框架上
# 从而让你能看得见它
fig.canvas.blit(fig.bbox)for j in range(100):# 将背景重置为画布状态,屏幕不变fig.canvas.restore_region(bg)# 更新artist, 画布状态和屏幕都保持不变ln.set_ydata(np.sin(x + (j / 100) * np.pi))# 重新渲染artist, 更新画布状态, 但不更新屏幕ax.draw_artist(ln)# 将图像复制到GUI状态,但屏幕可能尚未改变fig.canvas.blit(fig.bbox)# 刷新任何挂起的 GUI 事件,如果需要,重新绘制屏幕fig.canvas.flush_events()# 你可以旋转一个暂停在此如果你想要让整个过程降速# plt.pause(.1)

在这里插入图片描述

这个示例有效并显示了一个简单的动画,但是因为我们只抓取了一次背景,如果图形的像素大小发生变化(由于图形的大小或者dpi发生变化),背景就失效,并导致错误发生(但有时看起来会很酷,还有一个全局变量和相当多的样板,这表明我们应该将其包装在一个类中)。

2 基于类的示例

我们可以使用一个类来封装恢复背景、绘制artist,然后将结果传输到屏幕上的样板逻辑和状态。此外,每当发生完全重新绘制以正确处理调整大小时,我们使用"draw_event"回调来捕获新的背景。

class BlitManager:def __init__(self, canvas, animated_artists=()):"""Parameters----------canvas : FigureCanvasAggThe canvas to work with, this only works for subclasses of the Aggcanvas which have the `~FigureCanvasAgg.copy_from_bbox` and`~FigureCanvasAgg.restore_region` methods.animated_artists : Iterable[Artist]List of the artists to manage"""self.canvas = canvasself._bg = Noneself._artists = []for a in animated_artists:self.add_artist(a)# 在每次绘图上抓取背景self.cid = canvas.mpl_connect("draw_event", self.on_draw)def on_draw(self, event):"""Callback to register with 'draw_event'."""cv = self.canvasif event is not None:if event.canvas != cv:raise RuntimeErrorself._bg = cv.copy_from_bbox(cv.figure.bbox)self._draw_animated()def add_artist(self, art):"""Add an artist to be managed.Parameters----------art : ArtistThe artist to be added.  Will be set to 'animated' (justto be safe).  *art* must be in the figure associated withthe canvas this class is managing."""if art.figure != self.canvas.figure:raise RuntimeErrorart.set_animated(True)self._artists.append(art)def _draw_animated(self):"""Draw all of the animated artists."""fig = self.canvas.figurefor a in self._artists:fig.draw_artist(a)def update(self):"""Update the screen with animated artists."""cv = self.canvasfig = cv.figure# 如果错过了绘制事件,则什么也不画if self._bg is None:self.on_draw(None)else:# 还原背景cv.restore_region(self._bg)# 绘制所有的动画artistsself._draw_animated()# 更新GUI状态cv.blit(fig.bbox)# 让GUI事件循环处理所有它该干的事儿cv.flush_events()

以下是我们将如何使用我们的类。这是一个比第一种情况稍微复杂一些的例子,因为我们是学添加了一个文本框架计数器。

# 创建一个新的绘图
fig, ax = plt.subplots()
# 添加一条线
(ln,) = ax.plot(x, np.sin(x), animated=True)
# 添加帧序号
fr_number = ax.annotate("0",(0, 1),xycoords="axes fraction",xytext=(10, -10),textcoords="offset points",ha="left",va="top",animated=True,
)
bm = BlitManager(fig.canvas, [ln, fr_number])
# 确保你的窗口在屏幕上,绘图
plt.show(block=False)
plt.pause(.1)for j in range(100):#更新artistsln.set_ydata(np.sin(x + (j / 100) * np.pi))fr_number.set_text(f"frame: {j}")# 告诉位图传输管理器来更新bm.update()

在这里插入图片描述

此类不依赖于pyplot,适合嵌入到更大的GUI应用程序中。

在这里插入图片描述

这篇关于matplotlib从起点出发(15)_Tutorial_15_blitting的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/925247

相关文章

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Adblock Plus官方规则Easylist China说明与反馈贴(2015.12.15)

-------------------------------特别说明--------------------------------------- 视频广告问题:因Adblock Plus的局限,存在以下现象,优酷、搜狐、17173黑屏并倒数;乐视、爱奇艺播放广告。因为这些视频网站的Flash播放器被植入了检测代码,而Adblock Plus无法修改播放器。 如需同时使用ads

起点中文网防止网页调试的代码展示

起点中文网对爬虫非常敏感。如图,想在页面启用调试后会显示“已在调试程序中暂停”。 选择停用断点并继续运行后会造成cpu占用率升高电脑卡顿。 经简单分析网站使用了js代码用于防止调试并在强制继续运行后造成电脑卡顿,代码如下: function A(A, B) {if (null != B && "undefined" != typeof Symbol && B[Symbol.hasInstan

matplotlib绘图中插入图片

在使用matplotlib下的pyplot绘图时,有时处于各种原因,需要采用类似贴图的方式,插入外部的图片,例如添加自己的logo,或者其他的图形水印等。 一开始,查找到的资料都是使用imshow,但是这会有带来几个问题,一个是图形的原点发生了变化,另外一个问题就是图形比例也产生了变化,当然最大的问题是图形占据了整个绘图区域,完全喧宾夺主了,与我们设想的只在绘图区域中占据很小的一块不相符。 经

15 组件的切换和对组件的data的使用

划重点 a 标签的使用事件修饰符组件的定义组件的切换:登录 / 注册 泡椒鱼头 :微辣 <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-

matplotlib中文乱码问题

在使用Matplotlib进行数据可视化的过程中,经常会遇到中文乱码的问题。显示乱码是由于编码问题导致的,而matplotlib 默认使用ASCII 编码,但是当使用pyplot时,是支持unicode编码的,只是默认字体是英文字体,导致中文无法正常显示,所以显示中文乱码。 文本使用系统默认字体、手动指定字体、使用字体管理器来解决。 一、系统默认字体(全局设置字体) 在Matplotlib中

Matplotlib图像读取和输出及jpg、png格式对比,及透明通道alpha设置

图像像素值 图像像素值一般size为3,也就是通道数,分别代表R,G,B,如果只有单一 一个值则表示灰度值,也就是说一张二维图片,当长和宽都为1080时,那么若是灰度图像,图像尺寸为(1080,1080,1)若是RGB图像则为(1080,1080,3), jpg、png图像格式 jpg图像的灰度值范围和RGB范围为[0,255],数值类型为uint8,也就是无符号整数 png图像的灰度值范

使用matplotlib绘制散点图、柱状图和饼状图-学习篇

一、散点图 Python代码如下: num_points = 100x = np.random.rand(num_points) #x点位随机y = np.random.rand(num_points) #y点位随机colors = np.random.rand(num_points) #颜色随机sizes = 1000 * np.random.rand(num_points) # 大

java基础总结15-面向对象11(抽象类)

下面通过一下的小程序深入理解抽象类 因此在类Animal里面只需要定义这个enjoy()方法就可以了,使用abstract关键字把enjoy()方法定义成一个抽象方法,定义如下:public abstract void enjoy();   从某种意义上来说,抽象方法就是被用来重写的,所以在父类声明的抽象方法一定要在子类里面重写。如果真的不想在子类里面重写这个方法,那么可以再在子类里