《WebKit 技术内幕》之八(3):硬件加速机制

3 其他硬件加速模块

3.1 2D图形的硬件加速机制

        其实网页中有很多绘图操作是针对2D图形的,这些操作包括通常的网页绘制,例如绘制边框、文字、图片、填充等,它们都是典型的2D绘图操作。在HTML5中,规范又引入了2D绘图的画布功能,它的作用是提供2D绘图的JavaScript接口,所以JavaScript代码可以很容易地调用该接口来绘制任意的2D图形。2D绘图本身是使用2D的图形上下文,而且一般使用软件方式来绘制它们,也就是光栅化(Rasterize)的方法。但是,其实这些2D绘图操作也可以使用GPU也就是3D绘图来完成,这里把使用GPU来绘制2D图形的方法称为2D图形的硬件加速机制。

        如上面所述,目前2D图形的硬件加速有两种应用场景,第一种就是网页基本元素的绘制,针对的层次类型其实在前面描述过,也就是ContentLayer,读者应该记得它的后端是一个2D的画布对象;第二种就是HTML5的新元素canvas,用来绘制2D图形。

3.1.1 2D图形上下文

        第7章中介绍了WebKit中的2D图形上下文,该上下文在WebKit的Chromium移植中需要使用Skia图形库来完成2D图形操作,图8-26描述了WebKit的Chromium移植中2D图形上下文的实现类。

                        图WebKit的Chromium移植使用Skia来绘制2D图形

        在上图中,对于WebKit需要使用GraphicsContext的地方,Chromium会创建一个Skia图形库中提供的SkCanvas对象来处理WebKit的2D图形操作请求。至于这个SkCanvas对象是使用软件绘图还是GPU绘图,取决于对SkCanvas对象的设置。SkCanvas类表示的是一个画布,2D的图形操作都是在这个画布上处理,绘制结果也是保存在SkCanvas对象中。如果调用者需要使用软件方式来绘图,如图中左半部分所示,那么调用者需要创建一个基本的SkDevice对象,该对象使用光栅扫描的方法来一一计算绘制的像素结果,并把结果存入SkBitmap对象中。SkBitmap对象使用一块CPU内存,该内存中保存的是一个个像素值,典型的例如RGBA格式。

        如果调用者需要使用GPU硬件来进行绘图,那么在创建SkCanvas对象的时候,通过传入SkSurface_Gpu对象即可。当然创建SkSurface_Gpu对象需要很多其他的对象,最重要的是SkGpuDevice对象,它是SkDevice的一个基类,同原先软件方式不同的是,它是将2D图形操作转变成对GL的操作,使用GrContext的3D图形上下文来绘制,并将结果存储在GrRenderTarget,该存储目标是GPU的内存缓冲区。

        从上面的讨论可以看出,WebKit调用GraphicsContext对象的时候,WebKit根本不知道下层实际使用的是软件还是GPU来绘制2D图形,这一切都是由Skia图形库来完成的,当需要启动硬件加速的时候,Chromium只需要为SkCanvas对象设置相应的对象即可。

3.1.2 Canvas 2D

        “canvas”是HTML5中新加入的元素,在最开始的时候它只是一个2D画布对象,网页开发者可以使用规范定义的JavaScript接口在画布上绘制任意的2D图形,这样的技术我们称之为Canvas 2D。不过,Khronous组织提出可以在该元素上使用JavaScript接口绘制3D图形,这样的技术我们称之为WebGL或者Canvas3D,这个稍后会做介绍。一个“canvas”元素的对象只能绘制2D图形和3D图形中的一种,不能够同时绘制这两者。

        “canvas”元素的“getContext”方法包含一个参数,该参数用来指定创建上下文对象的类型。对于2D的图形操作,通过传递参数值“2d”,浏览器会返回一个2D图形上下文,称为CanvasRenderingContext2D,它提供了用于绘制2D图形的各种应用程序编程接口,包括基本图形绘制(如线、矩形、圆弧)、文字绘制、图形变换、图片绘制及合成等。

        前面说到,CanvasRenderingContext2D是2D图形绘制的上下文对象,其提供了用于绘制2d图形的API,W3C工作组起草了标准的草案。该对象由JavaScript代码调用“getContext()”函数创建,Web开发者便可以调用它的编程接口在画布上绘制2D图形了。这些编程接口主要的作用就是在画布上绘制点、线、矩形、弧形、图片等,除此之外,还提供了这些绘制的样式和合成效果等。示例代码8-3给出了使用Canvas2D技术的基本方法。

        Canvas 2D可以使用软件方法来绘图,也可以使用GPU来加速绘图,根据前面介绍的2D图形上下文和Chromium中使用Skia图形库来绘图的方法,网页的Canvas 2D技术同样需要借助Skia这一技术。图8-27描述了Canvas 2D使用GPU来绘图所涉及的一些主要类。对于软件绘图来说,Chromium的工作过程实际上更简单一些,图中ImageBuffer只是使用SkCanvas、SkDevice和SkBitmap等类,这一过程其实不如硬件加速绘图复杂,所以这里不再赘述。

示例代码(使用Canvas2D技术的网页代码)

                                图(使用GPU硬件绘图的Canvas2D技术)

        HTML5的Canvas2D机制使用了一个GraphicsContext对象,也就是2D图形上下文,同时还包括一个ImageBuffer对象来表示canvas绘制的结果,这里软件绘图和GPU硬件加速绘图没有什么大的不同。回到GPU硬件绘图上来说,如果使用硬件加速机制的话,Chromium会创建一个SkDeferredCanvas对象,该对象的特别之处在于它采用延迟机制来绘制2D图形,随后介绍。该对象当然需要SkGpuDevice来将2D绘图操作转换为使用3D图形上下文来绘制,这一过程跟上一小节介绍的非常类似。笔者需要强调的是图中的Canvas2DLayerBridge类,它是一个桥接类,因为实际上2D图形是使用3D图形接口绘制的,所以Chromium需要3D图形上下文和一些准备工作,这些都是在该类中完成。

                WebGraphicsContext3DCommandBufferImpl类之后的部分跟图8-12介绍的过程完全一样,在这种情况下,上层是2D绘图还是3D绘图已经完全没有差别了。

        下面用三个阶段来描述Chromium是如何使用硬件加速绘图来支持HTML5的Canvas2D功能的,以示例代码8-3作为例子加以说明。首先看第一阶段。

        第一阶段这里称为初始化阶段,也就是示例代码(使用Canvas2D技术的网页代码)中调用“fillStyle”的阶段,因为该函数会触发建顺序图(Canvas2D初始化阶段的对象创中这些对象的创建。基本上,这一阶段的代码需要WebKit和Chromium创建图8-28所涉及类的对象,读者可以理解一下它们的顺序。其中GraphicsContext类主要是被CanvasRendering-Context2D类所使用,而GraphicsContext3D类是被Canvas2DLayerBridge类使用。这里面还需要强调的一点就是合成器中的CC::Layer(还包括WebLayer,限于图片太大,没有画出),它是由Canvas2DLayerBridge类创建,这听起来有点奇怪,因为CC::Layer类和GraphicsLayer类是一一对应的。不过没关系,因为在这里,“canvas”元素对应的RenderLayer对象还没有被创建,它在第二阶段才会创建,这是为什么呢?回想之前的介绍,在DOM创建过程中,当WebKit构建canvas元素的对象时,并没有为它创建RenderLayer对象,因为这是延迟执行的。如果“canvas”元素没有创建2D或者3D图形上下文,它是不需要RenderLayer对象的,当然也就没有RenderLayerBacking对象,更没有GraphicsLayer对象。同时,这段JavaScript代码在DOM构建过程中会被调用,这就造成了上面所述的这种情况。

        建顺序图(Canvas2D初始化阶段的对象创

        第二阶段是WebKit构建RenderLayer等对象。在DOM树构建完之后,WebKit会检查有无变化的CSS样式,在这里JavaScript代码改变了canvas元素的属性,所以WebKit会更新RenderObject树和RenderLayer树。图(为Canvas元素创建RenderLayer等并设置GraphicsLayer)描述了这一阶段。

                        图(为Canvas元素创建RenderLayer等并设置GraphicsLayer)

        在这里,笔者不想重复RenderLayer等对象的创建,而想重点强调GraphicsLayer对象如何设置自己的WebLayer成员变量。方法是这样的:WebKit中的RenderLayerBacking对象检查是否是canvas元素,如果是,RenderLayerBacking对象从HTMLCanvasElement对象中获得CanvasRenderingContext2D对象,这一上下文对象的platformLayer函数能够得到之前创建的WebLayer对象,这样WebKit就建立了RenderLayer和GraphicsLayer的映射关系。为了简洁起见,图中省略了一些步骤。

        第三个阶段就是绘图部分。图8-30详细描述了这一思想和主要过程。Chromium采用缓存模式来处理JavaScript代码的2D图形操作,也就是说,当JavaScript通过标准的接口调用2D图形的时候,Chromium使用SkDeferredCanvas对象保存2D图形操作,当Chromium需要绘制一个新帧的时候,Skia图形库才会一次性提交并绘制这些缓存的操作。

                        图(Chromium中的Canvas2D绘图过程)

        先看图中的上半部分,当JavaScript调用2D绘图接口时需要使用contextAcquired()函数获取2D图形上下文,Chromium据此判断后面修改画布的内容,所以Chromium会使用Canvas2DLayerManager类来设置一个TaskObserver对象到主消息循环,这样做的好处是等到JavaScript代码调用2D绘图接口之后,才会触发真正的绘图动作。而JavaScript代码调用的这些操作都是依靠SkDeferredCanvas来保存的。

        图中的下半部分表示当前面JavaScript调用2D绘图接口完毕后,WebKit调用TaskObserver类的didProcessTask方法。Canvas2DLayerManager类调用CanvasLayerBridge类来判断是否需要刷新那些操作。Canvas2DLayerBridge类检查并重置前面设置的标记,如果时机合适的话,该类调用SkDeferredCanvas类的flush函数提交前面保存的所有绘图操作,这样就完成了Canvas2D的绘制工作。

        当合成器调用updateLayers函数的时候,该函数会触发每个合成层绘制自己。因为Canvas2D机制是由JavaScript代码来绘制2D图形,所以这个时候canvas所在的合成层实际上已经绘制完成(或者说绘制操作已经缓存起来了)。图8-31描述了合成器要求绘制Canvas2D的合成层的过程,读者可以看到,这时候WebKit实际上不需要绘制该层,只需要改变一下3D图形上下文的状态。

                        图(Chromium中合成器调用绘制Canvas2D的合成层)

        从中读者可以发现,这一机制虽然延迟了一些操作(实际上没有什么影响),但是Chromium采用的这一延迟思想非常有用,也就是合并很多2D绘图操作 (5) ,这样能够有效提高绘制的性能。

3.2 WebGL

3.2.1 3D图形上下文

        前面提到过3D图形上下文,WebCore表示该上下文的抽象类是GraphicsContext3D。WebKit的Chromium移植定义了WebGraphicsContext3D接口,该接口类是GraphicsContext3D的实现类,基本上实现类的所有接口都可以映射到OpenGL ES 2.0 规范所定义的编程接口。

        图(3D图形上下文和Chromium的实现类)中包含了三个类,最下面的类就是WebGraphicsContext3DCommandBufferImpl,该类是WebGraphicsContext3D类对应的使用命令缓冲区的实现子类。前面提到的合成过程和Canvas2D,包括本节介绍的WebGL都会使用该类来实现3D图形操作。

                                图(3D图形上下文和Chromium的实现类)

3.2.2 WebGL的实现

        WebGL是Khronous组织提出的一套基于3D图形定义的JavaScript接口,它基于canvas元素,跟Canvas2D不同的是,Web开发者可以使用3D图形接口来绘制各种3D图形。根据WebGL规范中的描述,这些接口可以分成下面几个主要的部分。

  • 上下文及内容展示 :在使用WebGL的编程接口之前,开发者需要获取WebGL-RenderingContext和DrawingBuffer接口(Chromium需要它)。对JavaScript代码来说,GL的操作都是由WebGLRenderingContext对象来负责完成。但是,DrawingBuffer接口对用户来说是透明的,它用来存储渲染的内容并被合成器所合成,包括帧缓冲器对象(绘制的结果存储)和纹理对象(纹理被合成器所使用)。
  • WebGL的资源及其生命周期 :纹理对象、缓冲区(VBOs)、帧缓冲区、渲染缓冲区、着色器等(这些也都是OpenGL的资源)。它们有对应的JavaScript对象即与WebGLObject对应,这些对象的生命周期是一致的。
  • 安全 :WebGL规范为保证安全性,第一,所有的WebGL资源必须包含初始化的数据;第二,来源安全性,为防止信息泄露,当“canvas”元素的属性“origin-clean”为false时,readPixels将会抛出安全方面的异常;第三,要求所有的着色语言必须符合OpenGL ES Shading Language 1.0;第四,为防止DOS攻击,规范建议采取适当的措施对花费时间过长的渲染操作过程进行监控和限制。
  • WebGL接口 :主要包括各种资源类的接口和上下文类的接口,这些接口用于绘制3D的操作,它们基本上来源于OpenGL ES 2.0定义的接口。
  • WebGL与OpenGLES 2.0的区别 :这里不再一一介绍,读者可以自行翻阅和了解相关细节。读者假如想要了解自己的浏览器对WebGL支持的详细情况,请访问http://webglreport.sourceforge.net/获取详细参数。

        针对规范定义的内容,WebKit和Chromium定义了相应的类来描述它们,图8-33给出了主要类。WebGLRenderingContext类同CanvasRenderingContext2D类的作用类似,都是规范定义的接口。不同的是,WebGL的接口是3D图形操作。WebGLRenderingContext类同样需要一个GraphicsContext3D类和它的实现类,除此之外,还需要一个DrawingBuffer类,它类似于Canvas2D中的ImageBuffer,它的作用是保存WebGL渲染目标结果,WebKit将渲染结果用来合成。

                        图(WebKit和Chromium中支持WebGL的主要类)

        下面同样以例子来说明WebGL的工作过程,示例代码8-1中就是一个使用WebGL技术的网页,以此例为基础来描述这一个过程。跟Canvas2D的过程分析一样,这里同样也把Chromium中WebGL的工作过程分成三个阶段。

                第一阶段是对象的初始化阶段,当JavaScript引擎调用示例代码中的getContext函数的时候,WebKit就会执行如图8-34所示的对象创建顺序,这一过程跟Canvas2D的对象创建过程非常类似。不同的是,这一阶段不会创建CC::Layer对象。

                                图(WebGL初始化阶段的对象创建顺序)

        第二阶段是构建RenderLayer、WebLayer、CC::Layer等对象,同样是在DOM树构建之后检查CSS样式变化时才会被触发。当RenderLayer等对象被创建之后,WebKit设置GraphicsLayer对象所对应的WebLayer对象。同Canvas2D不一样的是,此时DrawingBuffer对象才会开始请求创建WebLayer(WebLayerImpl)和TextureLayer对象,之后WebKit同样将WebLayer对象设置到GraphicsLayer中。图8-35描述了这一过程,为了简洁起见,图中省略了一些步骤。

                        图(WebGL创建RenderLayer和TextureLayer等对象)

        第三阶段是3D绘图部分,图8-36是一个简单的WebGL使用clearColor接口来设置颜色的JavaScript代码被WebKit执行的过程。同Canvas2D机制不一样的是,每个GL的调用都是直接通过WebGraphicsContext3DCommandBufferImpl类将GL命令传给GPU进程,这一过程没有使用缓存机制,而是直接将命令传递给GPU进程。

                                                图(WebGL绘制3D图形)

         同样的,当合成器调用updateLayers函数的时候,该函数会触发WebGL所使用的合成层绘制合成层的目标结果到合成层的存储结果。WebGL所在层的内容在合成器请求更新该层之前已经由WebKit完成。图8-37描述了合成器要求绘制WebGL的合成层时候的过程,DrawingBuffer所要做的就是刷新3D图形上下文中的结果数据,并返回结果。

                                图(Chromium中合成器调用绘制WebGL的合成层)

3.3 CSS 3D变形

        CSS 3D变形和动画是HTML5引入的新特性,作用是能够对任意DOM子树作3D变形。这一特性非常有用,它同WebGL提供的能力是不一样的。WebGL是在一个“canvas”元素内部绘制3D图形,CSS 3D变形功能可以对任何元素进行3D变形,它是一个可以被元素子女继承的属性,也就是一个元素和它的子女都会作相应的3D变形。

        WebKit对应用该变形技术的DOM子树使用单独的合成层和硬件加速机制。当使用JavaScript代码改变该元素的3D变形样式后,Chromium能够减少网页每一帧渲染所需要的时间,典型的例子就是前面提到的网页,来自于www.famo.us。

         以示例代码6-1所展示的CSS 3D变形为例,说明3D变形是如何被WebKit和Chromium处理的。对于WebKit需要创建RenderLayer等对象,之前已经介绍过,这里不再赘述。图(设置合成器中的Layer对象的3D变形值)介绍了WebKit和Chromium设置3D变形值的过程。

                                图(设置合成器中的Layer对象的3D变形值)

        当网页中JavaScript代码修改元素的变换属性值的时候,通过上面的过程,最后样式是设置在该合成层(前景层)上,当WebKit将元素绘制完成之后,在合成过程中,WebKit通过3D变形作用到该合成层上,即可完成特定的效果。WebKit只是在第一次需要绘制“div”元素的内容,之后仅仅设置变换属性值,然后重新合成即可。当合成器调度绘制该合成层的时候,WebKit根本不会发生想象中的重新布局和重绘动作。虽然用户看起来网页内容在变动,但是这只是合成的动作,这些动画等都是WebKit和Chromium设计的机制和硬件加速带来的效果。

3.4 其他

        网页中还有很多其他的模块可以使用GPU硬件机制来加速,例如支持视频解码和播放、2D图形绘制等,WebKit支持它们的主要思想依旧是对这些内容进行分层,使用GPU的强大绘图能力来支持这些模块,关于视频方面的介绍,笔者将在第11章“多媒体”作进一步的阐述。读者还可以思考一下有没有其他地方可以使用加速机制。

        另外,还有很多新的思路对硬件加速机制进行改进,典型的做法是使用多线程机制,因为现代处理器都包含多核,使用线程化的方法来支持网页的渲染是一个很好的思路。当然线程化的代价就是WebKit需要同步或者内容的拷贝,例如前面介绍的线程化合成器、Layer树和LayerImpl树。Chromium为了减少同步和等待的开销,创建LayerImpl树并拷贝Layer树的内容,但是这一做法带来的好处也很明显。所谓有利也有弊正是如此,关键看应用场景的实际效果如何。

3.5 实践:Chromium的支持

        Chromium使用GPU加速机制来加速网页渲染被广泛地应用在各种网页中。Chromium浏览器对网页渲染的理解的确很不一样,在网页功能越来越强的同时,用户也能够取得较好的性能和体验效果。

        图(Chromium能够使用GPU加速的功能)描述了Chromium目前能使用GPU硬件加速的各项网页功能,这是在Windows系统上显示的结果,在其他平台上,结果可能不一样,例如在Android上面可能有更多跟加速相关的功能。图中的一些功能之前已经介绍过,例如Canvas、Compositing、3D CSS和CSS Animation、WebGL等。不过,还有些其他的功能笔者并没有介绍,例如Flash、Video、WebGL multisampling(WebGL中的反锯齿技术)等。除了Video之外,读者对其他功能有兴趣的话,可以自行参考相关材料。

                                图(Chromium能够使用GPU加速的功能)

        关于使用硬件加速和合成器的实践,读者可以回顾第2章中图2-5所描述的网页层次结构。相信读者现在对那些合成层,以及将合成层分成瓦片的理解更深了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/638798.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常用设计模式(工厂方法,抽象工厂,责任链,装饰器模式)

前言 有关设计模式的其他常用模式请参考 单例模式的实现 常见的设计模式(模板与方法,观察者模式,策略模式) 工程方法 定义 定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟到子类。 ——《设…

服务端实现微信小游戏登录

1 微信小程序用户登录及其流程 小程序可以通过微信官方提供的登录能力,便能方便的获取微信提供的用户身份标识,达到建立用户体系的作用。 官方文档提供了登录流程时序图,如下: 从上述的登录流程时序图中我们发现,这里总共涉及到三个概念。 第一个是小程序,小程序即我们…

【征服redis15】分布式锁的功能与整体设计方案

目录 1. 分布式锁的概念 2.基于数据库做分布式锁 2.1 基于表主键唯一做分布式锁 2.2 基于表字段版本号做分布式锁 2.3 基于数据库排他锁做分布式锁 3.使用Redis做分布式锁 3.1 redis实现分布式锁的基本原理 3.2 问题一:增加超时机制,防止长期持有…

【Python从入门到进阶】47、Scrapy Shell的了解与应用

接上篇《46、58同城Scrapy项目案例介绍》 上一篇我们学习了58同城的Scrapy项目案例,并结合实际再次了项目结构以及代码逻辑的用法。本篇我们来学习Scrapy的一个终端命令行工具Scrapy Shell,并了解它是如何帮助我们更好的调试爬虫程序的。 一、Scrapy Sh…

Java实现大学计算机课程管理平台 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 实验课程档案模块2.2 实验资源模块2.3 学生实验模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 实验课程档案表3.2.2 实验资源表3.2.3 学生实验表 四、系统展示五、核心代码5.1 一键生成实验5.2 提交实验5.3 批阅实…

第一篇【传奇开心果系列】beeware的toga开发移动应用:轮盘抽奖移动应用

系列博文目录 beeware的toga开发移动应用示例系列博文目录一、项目目标二、开发传奇开心果轮盘抽奖安卓应用编程思路三、传奇开心果轮盘抽奖安卓应用示例代码四、补充抽奖逻辑实现五、开发传奇开心果轮盘抽奖苹果手机应用编程思路六、开发传奇开心果轮盘抽奖苹果手机应用示例代…

【 CSS 】基础 2

“生活就像骑自行车,想要保持平衡,就得不断前行。” - 阿尔伯特爱因斯坦 CSS 基础 2 1. emmet 语法 1.1 简介 Emmet语法的前身是 Zen coding,它使用缩写,来提高 HTML / CSS 的编写速度, VSCode 内部已经集成该语法。…

webpack-dev-server原理解析及其中跨域解决方法

webpack proxy ,就是 webpack 提供的解决跨域的方案。其基本行为是接受客户端发送的请求后转发给其他的服务器,目的是为了解决在开发模式下的跨域问题。 原理 webpack中的proxy 工作原理是利用了 http-proxy-middleware 这个http 代理中间件,实现将请求…

专门为机器学习开发的jpy语言

这本来是一个为工科教学专门开发的附属品,并不是说Python或Java有多不好,根本上它就是一个Java工程教材,但又要结合人工智能。因此,出现了这样一个包容性的怪胎,可以用python一样的语法与Java一起编写。 没流行起来的一…

<信息安全>《2 国内主要企业网络安全公司概览(二)》

4 北京天融信科技有限公司(简称天融信) 信息内容LOGO成立日期创始于1995年总部北京市海淀区上地东路1号院3号楼北侧301室背景民营企业是否上市天融信[002212]A股市值99亿主要产品网络安全大数据云服务员工规模6000多人简介天融信科技集团(证券代码:0022…

【开源】基于JAVA的停车场收费系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 停车位模块2.2 车辆模块2.3 停车收费模块2.4 IC卡模块2.5 IC卡挂失模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 停车场表3.2.2 车辆表3.2.3 停车收费表3.2.4 IC 卡表3.2.5 IC 卡挂失表 四、系统实现五、核心代码…

在达沃斯,人工智能引发的乐观情绪可谓一分为二

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

基于STM32的基础实验(一)

LED实验 采用STM32单片机设计电路,控制LED灯的亮灭,对单片机端口的位操作进行演示。 实验需要: STM32核心板独立LED 电路原理图 LED灯实际上是一个特殊的二极管,通过控制高低电平亮灭。如图所示,当1为低电平&#…

数据可视化 | 期末复习 | 补档

文章目录 📚介绍可视化🐇什么是可视化🐇科学可视化,信息可视化,可视分析系统三者之间有什么区别🔥🐇可视化的基本流程🐇可视化的两个基本设计原则🐇数据属性&#x1f407…

数学建模学习笔记||层次分析法

评价类问题 解决评价类问题首先需要想到一下三个问题 我们评价的目标是什么我们为了达到这个目标有哪几种可行方案评价的准则或者说指标是什么 对于以上三个问题,我们可以根据题目中的背景材料,常识以及网上收集到的参考资料进行结合,从而筛…

GEE:最小距离分类器(minimumDistance)分类教程(样本制作、特征添加、训练、精度、最优参数、统计面积)

作者:CSDN @ _养乐多_ 本文将介绍在Google Earth Engine (GEE)平台上进行最小距离分类(minimumDistance)的方法和代码,其中包括制作样本点教程(本地、在线和本地在线混合制作样本点,合并样本点等),加入特征变量(各种指数、纹理特征、时间序列特征、物候特征等),运行…

本地git切换地区后,无法使用ssh访问github 22端口解决方案

问题 由于放假回家,发现之前一直使用正常的git,与github无法通讯,pull和push都无法连接。报错如下: connect to host github.com port 22: Connection timed out fatal: Could not read from remote repository. 原因 可能是所…

docker常用基础命令

文章目录 1、Docker 环境信息命令1.1、docker info1.2、docker version 2、系统日志信息常用命令2.1、docker events2.2、docker logs2.3、docker history 3、容器的生命周期管理命令3.1、docker create3.2、docker run 总结 1、Docker 环境信息命令 1.1、docker info 显示 D…

Linux 命令大全 CentOS常用运维命令

文章目录 1、Linux 目录结构2、解释目录3、命令详解3.1、shutdown命令3.1、文件目录管理命令ls 命令cd 命令pwd 命令tree 命令mkdir 命令touch 命令cat 命令cp 命令more 命令less 命令head 命令mv 命令rm 命令ln 命令tail 命令cut命令 3.2、用户管理useradd/userdel 命令用户的…

使用残差网络识别手写数字及MNIST 数据集介绍

MNIST 数据集已经是一个几乎每个初学者都会接触的数据集, 很多实验、很多模型都会以MNIST 数据集作为训练对象, 不过有些人可能对它还不是很了解, 那么今天我们一起来学习一下MNIST 数据集。 1.MNIST 介绍 MNIST 数据集来自美国国家标准与技术研究所, National Institute of S…