GStreamer 简明教程(二):基本概念介绍,Element 和 Pipeline

news2024/11/26 12:48:30

系列文章目录

  • GStreamer 简明教程(一):环境搭建,运行 Basic Tutorial 1 Hello world!

文章目录

  • 系列文章目录
  • 前言
  • 一、查看插件信息
    • 1.1 gst-inspect 介绍
    • 1.2 源码中运行 gst-inspect
    • 1.3 理解插件的基本信息
    • 1.4 插件与元素
    • 1.5 总结
  • 二、Basic tutorial 2: GStreamer concepts
    • 2.1 创建元素
    • 2.2 创建 Pipeline
    • 2.3 设置元素属性
    • 2.4 错误检查
    • 2.5 GStreamer 的 Bus
    • 2.6 代码清理
    • 2.7 练习
  • 参考


前言

在上一章中我们成功的搭建了 GStreamer 的调试环境,并运行了 Hello World 程序。本章我们将介绍 GStreamer 中的基本概念,包括 Element 和 Pipeline。另外,还介绍使用 gst-inspect-1.0 程序来查看插件的基本信息。

一、查看插件信息

1.1 gst-inspect 介绍

GStreamer 是基于插件的架构,它处处离不开插件,你几乎所有功能都是被封装在插件之中。因此如何查询插件信息是我们需要掌握的。

gst-inspect 是 GStreamer 框架提供的一个命令行工具,用于查询和观察 GStreamer 插件或元素的信息。通过使用 gst-inspect,用户可以检查一个 GStreamer 插件提供的元素类型,每个元素的属性,它们的源码位置等多种信息。

基础使用如下:

gst-inspect-1.0 [插件名|[元素名],这将返回具体插件的详细信息。

如果想要查找所有可用的插件和元素,可以运行 gst-inspect-1.0 命令。

执行 gst-inspect-1.0 [元素名] 可以查看某个具体元素的详细信息,包括它的功能描述,底层库的位置,已实现的接口,可用的参数以及参数的默认值等。

1.2 源码中运行 gst-inspect

我们已经搭建了源码环境,因此可以直接在源码环境中运行它,但注意调试环境变量的设置,关于调试环境的变量请参考 GStreamer 源码编译,在 Clion 下搭建调试环境。

在本人机器上,我将环境变量保存在一个 env.sh 文件中,gst-inspect 在工程编译完成后存放在

/Users/user/Documents/develop/gstreamer/buildDir/subprojects/gstreamer/tools/gst-inspect-1.0

有两种方式运行它:

  1. 编译完成后使用命令行运行,例如
source /Users/user/Documents/develop/gstreamer/env.sh
./gst-inspect-1.0 videotestsrc

2 在 Clion 上直接运行。设置好环境变量和相应参数即可
在这里插入图片描述

1.3 理解插件的基本信息

videosignal 这个插件为例,使用 gst-inspect 进行查看可以得到这个插件信息如下:

Plugin Details:
  Name                     videosignal
  Description              Various video signal analysers
  Filename                 /Users/user/Documents/develop/gstreamer/buildDir/subprojects/gst-plugins-bad/gst/videosignal/libgstvideosignal.dylib
  Version                  1.25.0.1
  License                  LGPL
  Source module            gst-plugins-bad
  Documentation            https://gstreamer.freedesktop.org/documentation/videosignal/
  Binary package           GStreamer Bad Plug-ins git
  Origin URL               Unknown package origin

  simplevideomark: Video marker
  simplevideomarkdetect: Video detecter
  videoanalyse: Video analyser

  3 features:
  +-- 3 elements

这是一个叫做 “videosignal” 的 GStreamer 插件的详细信息:

  • 插件名称(Name):videosignal。这是插件的名字,是唯一的。

  • 插件描述(Description):Various video signal analysers。这是对插件功能的简单描述,即该插件包含了不同的视频信号分析工具。

  • 包含文件(Filename):/Users/user/Documents/develop/gstreamer/buildDir/subprojects/gst-plugins-bad/gst/videosignal/libgstvideosignal.dylib。这是插件库的具体位置。

  • 版本(Version):1.25.0.1。这是插件的版本。

  • 许可证(License):LGPL。这是插件的开源许可证。

  • 源代码所在模块(Source module):gst-plugins-bad。这是包含源代码的模块名称。

  • 文档链接(Documentation):https://gstreamer.freedesktop.org/documentation/videosignal/。这是插件的详细文档链接。

  • 二进制包(Binary package):GStreamer Bad Plug-ins git。这是插件对应的二进制包名。

  • 原始 URL(Origin URL):Unknown package origin。这是插件源代码的原始 URL,但在这里没有给出具体的 URL。

  • 功能特性(Features):简单的视频标记器(simplevideomark)、视频检测器(simplevideomarkdetect)、视频分析器(videoanalyse)。插件的功能清单,这个插件主要提供了三个特性或者元素,它们分别是视频标记器、视频检测器和视频分析器。

1.4 插件与元素

GStreamer 框架的插件通常被分为几个集合或者类别:“base”, “good”, “ugly”, “bad” 和 “libav”。

“base” 是基础的插件,提供框架的核心功能,所有人都需要它们。

“good” 是高质量的插件,它们对于许多应用来说是有用的,而且它们的质量和稳定性得到了 GStreamer 开发团队的保证。

“ugly” 是功能有用但是由于许可证问题或者质量问题没有被包含在 “good” 类别中的插件。

“bad” 插件集合包含了那些质量不够好,或者因为没有足够的测试和文档,而无法被分类为 good 或 ugly 的插件。但是请注意,“bad” 只是暗示它们可能不稳定或者有缺陷,并不意味着它们不可用。许多 “bad” 类别的插件其实功能强大,只是还没有达到 GStreamer 团队的标准。

例如 videosignal 这个插件它是来源于 gst-plugins-bad 时,用户应该意识到这些插件可能具有一些缺陷或者是实验性的,需要谨慎使用。

一个插件包含一个或者多个元素,例如 videosignal 包含了三个元素分别是 simplevideomarksimplevideomarkdetectvideoanalyse;而 videotestsrc 它只包含一个元素 videotestsrc,插件和元素同名,当你使用

gst-inspect-1.0  videotestsrc

命令时它会优先输出元素的信息,当然也可以加上 --plugin 参数让它输出插件信息

gst-inspect-1.0 --plugin videotestsrc

每个插件其实对应的是一个动态库 so 文件。

1.5 总结

让我们总结下这块内容:

  1. GStreamer 中有很多插件集合,这些插件集合中包含多个插件
  2. 每个插件对应一个 so 动态库文件,每个插件包含一个或者多个元素
  3. gst-inspect-1.0 命令可以查看插件或者元素的信息

二、Basic tutorial 2: GStreamer concepts

让我们过一遍 Basic tutorial 2: GStreamer concepts中的内容。具体代码大家自己看,就不贴了。

在 GStreamer 中,元素是最基本的模块,大致可以分为这么几类:

  1. Source,负责生产数据。例如 videotestsrc 负责生成测试图像数据。
  2. Filter,负责处理数据,例如一些滤镜之类的。
  3. Sink,负责消费数据,例如将数据显示到屏幕上,或者保存到本地。

数据从 Source(数据生产者) 流向 Sink(数据消费者),过程中经过 FIlter 的处理。元素之间相互连接,组合一个 Pipeline。
在这里插入图片描述

2.1 创建元素

source = gst_element_factory_make ("videotestsrc", "source");
sink = gst_element_factory_make ("autovideosink", "sink");

gst_element_factory_make 是一个 GStreamer 的函数,用于创建一个新的元素实例。

函数原型:

GstElement * gst_element_factory_make (const gchar * factoryname, const gchar * name);

参数:

  • factoryname:元素工厂的名称,也就是你想要创建的 GStreamer 元素的类型名称,比如 “fakesrc”, “filesrc” 等。

  • name:新创建的元素实例的名称。这个参数是可选的,如果传入 NULL 或者一个空字符串,GStreamer 会自动为新元素生成一个唯一的名称。

返回值:

  • 这个函数返回一个指向新创建的 GStreamer 元素的指针。如果由于某种原因(比如指定的元素工厂名称不存在)无法创建元素,那么这个函数会返回 NULL。

在教程中,我们创建了两个元素:videotestsrc 和 autovideosink。videotestsrc 是 Source 类型的,因为你去查它的 pad 信息可以发现它只有一个 src 类型的 pad,而 autovideosink 是 Sink 类型的,因为它只有一个 sink 类型的 pad。这里的 pad 概念,我们后面在介绍,它是一个数据之间传输的接口。

“videotestsrc”是一个 Source 元素(它产生数据),用于创建测试视频模式。这个元素主要用于调试目的(和教学),并且通常不会在实际应用中找到。

“autovideosink”是一个 Sink 元素(它消费数据),它在窗口上显示接收到的图像。存在多种视频汇元素,取决于操作系统,具有不同程度的能力。autovideosink 会自动选择并实例化最好的一个,因此你无需关心具体细节,你的代码也更具有平台独立性。

因此在我们教程中,Pipeline 如下图:
在这里插入图片描述

2.2 创建 Pipeline

刚才我们只是创建了元素,并没有将它们进行关联起来。现在,我们创建一个 pipeline

pipeline = gst_pipeline_new ("test-pipeline");

gst_pipeline_new是GStreamer库中的一个函数,其允许创建一个新的管道元素。

gst_pipeline_new的函数原型为:

GstElement* gst_pipeline_new (const gchar *name);

该函数接收一个name参数,该参数为管道元素的名字。该函数的返回值是一个新创建的管道元素,以GstElement*类型的指针形式返回。

在GStreamer中,一个管道(pipeline)代表了一个数据流处理链。管道由多个处理元素(element)组成,每个元素都可以进行一种特定的数据处理任务,如解码、分析、合成等。各个元素之间通过pad进行数据的输入和输出。

通过gst_pipeline_new创建的管道仍然是空的,需要通过添加并连接各种元素来完成数据的处理链。例如,播放一个音频文件可能需要先读取文件数据,然后解码,再进行播放,这就需要分别添加文件源元素(filesrc)、解码元素(decodebin)和音频播放元素(alsasink)到管道,并将它们连接起来。

接下来,我们将元素添加到 pipeline 上,并连接它们

 /* Build the pipeline */
  gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
  if (gst_element_link (source, sink) != TRUE) {
    g_printerr ("Elements could not be linked.\n");
    gst_object_unref (pipeline);
    return -1;
  }

这段代码的主要目的是构建一个GStreamer的pipeline,并将source元素和sink元素添加到pipeline中,然后尝试将这两个元素链接起来。

gst_bin_add_many的函数原型为:

gboolean gst_bin_add_many (GstBin * bin, GstElement * element_1, ..., NULL);

它是一个变参函数,允许你添加多个元素到指定的bin中。这里的sourcesink就是你要添加到pipeline(这里需要显式转换为GstBin*类型)中的元素。

gst_element_link的函数原型为:

gboolean gst_element_link (GstElement *element_1, GstElement *element_2);

它主要用来将两个元素链接起来。GStreamer中的数据流是从源元素流向目的元素的,所以这行代码是尝试将source元素链接到sink元素。链接成功返回TRUE,否则返回FALSE。

所以这段代码的流程为:

  • sourcesink添加到pipepline中
  • 尝试链接sourcesink,如果不能链接,则打印错误信息,并释放pipeline的引用,返回-1。

2.3 设置元素属性

GStreamer 中每种元素都是一个 GObject,而 GObject 提供了属性设置的能力。

GStreamer 元素都有或多或少的属性可以设置,以 videotestsrc 为例,通过 gst-inspect 命令来查看它的属性,例如下面是一部分属性:

Element Properties:

  animation-mode      : For pattern=ball, which counter defines the position of the ball.
                        flags: readable, writable
                        Enum "GstVideoTestSrcAnimationMode" Default: 0, "frames"
                           (0): frames           - frame count
                           (1): wall-time        - wall clock time
                           (2): running-time     - running time
  
  automatic-eos       : Automatically EOS when the segment is done
                        flags: readable, writable
                        Boolean. Default: true
  
  background-color    : Background color to use (big-endian ARGB)
                        flags: readable, writable, controllable
                        Unsigned Integer. Range: 0 - 4294967295 Default: 4278190080 
  
  blocksize           : Size in bytes to read per buffer (-1 = default)
                        flags: readable, writable
                        Unsigned Integer. Range: 0 - 4294967295 Default: 4096 
  
  pattern             : Type of test pattern to generate
                        flags: readable, writable
                        Enum "GstVideoTestSrcPattern" Default: 0, "smpte"
                           (0): smpte            - SMPTE 100% color bars
                           (1): snow             - Random (television snow)
                           (2): black            - 100% Black
                           (3): white            - 100% White
                           (4): red              - Red
                           (5): green            - Green
                           (6): blue             - Blue
                           (7): checkers-1       - Checkers 1px
                           (8): checkers-2       - Checkers 2px
                           (9): checkers-4       - Checkers 4px
                           (10): checkers-8       - Checkers 8px
                           (11): circular         - Circular
                           (12): blink            - Blink
                           (13): smpte75          - SMPTE 75% color bars
                           (14): zone-plate       - Zone plate
                           (15): gamut            - Gamut checkers
                           (16): chroma-zone-plate - Chroma zone plate
                           (17): solid-color      - Solid color
                           (18): ball             - Moving ball
                           (19): smpte100         - SMPTE 100% color bars
                           (20): bar              - Bar
                           (21): pinwheel         - Pinwheel
                           (22): spokes           - Spokes
                           (23): gradient         - Gradient
                           (24): colors           - Colors
                           (25): smpte-rp-219     - SMPTE test pattern, RP 219 conformant

通过设置 pattern 这个属性让 videotestsrc 生成不同的画面,例如 pattern=0 生成是经典的条纹画面;pattern=1 则生成白噪声画面。

g_object_set (source, "pattern", 0, NULL);

在这里插入图片描述

在这里插入图片描述

2.4 错误检查

现在 Pipeline 建立好了,接下来就像前一章一样,修改 Pipeline 的状态,让它跑起来,但这次我们加上错误检查的逻辑

ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
  if (ret == GST_STATE_CHANGE_FAILURE) {
    g_printerr ("Unable to set the pipeline to the playing state.\n");
    gst_object_unref (pipeline);
    return -1;
  }

在这里,我们调用了gst_element_set_state()函数,但这次对其返回值进行了错误检查。

/* Wait until error or EOS */
bus = gst_element_get_bus (pipeline);
msg =
    gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
    GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

gst_bus_timed_pop_filtered() 会等待执行结束并返回一个 GstMessage。我们要求gst_bus_timed_pop_filtered()在GStreamer遇到错误条件或EOS时返回,因此我们需要检查到底发生了什么,并在屏幕上打印一条消息(你的应用程序可能会想采取更复杂的操作)。

/* 解析消息 */
  if (msg != NULL) {
    GError *err;
    gchar *debug_info;

    switch (GST_MESSAGE_TYPE (msg)) {
      case GST_MESSAGE_ERROR:
        gst_message_parse_error (msg, &err, &debug_info);
        g_printerr ("Error received from element %s: %s\n",
            GST_OBJECT_NAME (msg->src), err->message);
        g_printerr ("Debugging information: %s\n",
            debug_info ? debug_info : "none");
        g_clear_error (&err);
        g_free (debug_info);
        break;
      case GST_MESSAGE_EOS:
        g_print ("End-Of-Stream reached.\n");
        break;
      default:
        /* 我们不应该到达这里,因为我们只要求ERROR和EOS */
        g_printerr ("Unexpected message received.\n");
        break;
    }
    gst_message_unref (msg);
  }

GstMessage是一个非常通用的结构,可以传递几乎任何类型的信息。幸运的是,GStreamer为每种类型的消息提供了一系列解析函数。

在这个例子中,一旦我们知道消息包含一个错误(通过使用GST_MESSAGE_TYPE()宏),我们就可以使用gst_message_parse_error(),它返回一个GLib的GError错误结构和一个用于调试的字符串。你可以查看代码来看看这些是如何被使用和在之后被释放的。

2.5 GStreamer 的 Bus

GStreamer总线是一个非常重要的组件,它的任务是把元素生成的消息(GstMessages)按照顺序发送到应用程序线程。之所以强调线程,因为真正的媒体流传输是在另一个和应用程序不同的线程中进行的。

GstMessages可以通过调用 gst_bus_timed_pop_filtered() 函数以及其它相关函数来同步提取,也可以通过使用信号(这将在下一个教程中详细介绍)来异步提取。重要的是,你的应用程序总是需要监控总线,以便在发生错误和其他播放相关问题时得到通知。

2.6 代码清理

C 对比 C++,清理资源是比较麻烦和啰嗦的。在 GStreamer 中哪些接口返回的对象要清理,要调用哪个接口进行清理,函数的注释往往会没有写清楚。一种简单的方案就是去源码搜索,例如搜索 gst_element_get_bus,我在 basesrc.c 中看到它使用了 gst_object_unref (bus); 进行清理;同理还有 gst_bus_timed_pop_filtered,搜索后在 appsrc.c 中看到使用了 gst_message_unref (msg); 进行清理

2.7 练习

在 source 和 sink 之间添加一个 vertigotv filter,效果挺酷的,如下图
在这里插入图片描述
重要代码如下,完整代码参考 basic-tutorial-2-exercise.c

  /* Create the elements */
  source = gst_element_factory_make("videotestsrc", "source");
  filter = gst_element_factory_make("vertigotv", "filter");
  sink = gst_element_factory_make("autovideosink", "sink");

  /* Create the empty pipeline */
  pipeline = gst_pipeline_new("test-pipeline");

  if (!pipeline || !source || !sink) {
    g_printerr("Not all elements could be created.\n");
    return -1;
  }

参考

  • GStreamer 源码编译,在 Clion 下搭建调试环境
  • Basic tutorial 2: GStreamer concepts
  • basic-tutorial-2-exercise.c

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

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

相关文章

Stable Diffusion XL【模型推荐】沙雕手绘Lora,贼开心!不要问我这个有什么用,因为只有真正懂沙雕的才知道

前言 hello,大家好** 看惯了满屏的精致画面,咱们也来改改画风。今天老徐给大家带来了一款别有风趣的Lora模型——YFilter_ShaDiaoShouHui沙雕手绘模型。看腻了精致严谨的作品,这块模型肯定让你觉得太惊艳了。用作者的话说——不要问我这个Lo…

二叉树------最小堆,最大堆。

什么是最小堆: 堆是一种二叉树,最小堆中所有父亲节点的值都要比自己的子节点的值要小。而根节点称为堆顶。根据定义我们可以得到堆中最小元素就在堆顶。(节点左上角是编号,内部是元素值) 假设该图中的堆顶元素是24呢&a…

【Python】Python单元测试

文章目录 01-单元测试基础什么是单元测试常用的文件结构运行单元测试 02. 断言函数03. Test Fixtures什么是Test Fixtures模块级别的Fixtures类级别的Fixtures方法级别的Fixtures 04.Mock 01-单元测试基础 什么是单元测试常用的文件结构编写第一个单元测试运行单元测试 什么是单…

在CentOS 7 上安装和配置 uwsgi 详细教程

本章教程,主要记录在CentOS7中成功安装uwsgi的详细步骤。 1. 更新系统包 首先,更新系统的包管理器以确保你有最新的软件包信息: sudo yum update -y2. 安装Python和pip CentOS 7 默认提供 Python 2.7,但你可能需要安装 Python 3 及其对应的 pip。以下是安装 Python 3 和…

OpenCV—二值化Threshold()、adaptiveThreshold()

cv2.threshold() c:double cv::threshold ( InputArray src, OutputArray dst, double thresh, double maxval, int type ) (注:源图片, 目标图, 阈值, 填充色, 阈值类型) python:cv.threshold(src,thresh, maxval, type[, dst]) src:源图片…

顶顶通呼叫中心中间件-通话之前录音配置方法(mod_cti基于FreeSWITCH)

顶顶通呼叫中心中间件-通话之前录音配置方法(mod_cti基于FreeSWITCH) 1、修改配置文件 点击配置文件 -> 点击vars -> 根据图中配置 -> 点击提交XML ->重新启动freeswitch 修改成true就是电话接通开始录音&#xff0c;修改成false就是通话之前开始录音。 <!--应…

ES环境搭建、ES安装

文章目录 简介与环境搭建全文检索倒排索引ElasticSearchWindows安装ES下载配置JDK环境启动ES服务 centos7安装ES下载ElasticSearch创建es用户配置JDK环境配置ElasticSearch配置JVM参数启动ElasticSearch服务常见启动报错 客户端Kibana安装下载修改Kibana.yml运行Kibana访问 ES安…

IntelliJ IDEA全新版的0个新特性【送源码】

jetBrains刚刚发布了最新IntelliJ IDEA 2024.2版本&#xff0c;做了不少优化性能方面的优化&#xff0c;同时新的ui也默认为启动ui。感兴趣的小伙伴可以下载体验&#xff0c;以下为官方本次介绍&#xff1a; 借助 IntelliJ IDEA 2024.2 Ultimate&#xff0c;您可以直接在 IDE …

宝塔面板实现定时任务删除 logs文件 加条件删除 只删除一个月前的日志

我们在开发中难免用到了日志功能&#xff0c;随着日志越来越多导致占用我们的内存 下面是一个简单的 使用宝塔面板里面的定时任务来实现删除日志案例 第一步 首先我的日志文件目录 都在log文件夹里面&#xff0c; 每个月生成一个日志文件夹 文件夹命名是年月来命名的 第二…

JVM(一) 类加载器、类加载过程、JVM参数设置

JVM Java编译器 Java源文件在通过编译器之后被编译成相应的.Class文件&#xff08;字节码文件&#xff09; JVM解释器 .Class文件又被JVM中的解释器编译成机器码在不同的操作 系统&#xff08;Windows、Linux、Mac&#xff09;上运行。每种操作系统的解释器都是不同的&#xf…

SpringBoot起步依赖和配置

目录 起步依赖 目的 1 继承父工程&#xff0c;确定版本信息 2 添加 starter-web 坐标信息 配置 配置文件的分类 ​编辑实操 1 后缀名是.properties文件修改端口号&#xff0c;把原本的默认端口号8080改为8082 2 创建后缀名是.yaml文件&#xff0c;尝试修改端口号&…

ARM——体系结构

计算机体系结构&#xff1a;冯诺伊曼 哈佛 冯诺依曼结构 冯诺依曼结构&#xff0c;也称冯诺依曼模型或普林斯顿结构&#xff0c;是根据冯诺依曼提出的存储程序概念设计的计算机体系结构。其主要特点包括&#xff1a; 存储程序&#xff1a;指令与数据都…

【Qt】信号与槽(下)

目录 自定义信号 带参数的信号和槽 信号和槽存在的意义 信号与槽的连接方式 一对一 一对多 多对一 意义 信号和槽的其他说明 信号和槽的断开 使用Lambda表达式定义槽函数 信号与槽的优缺点 优点: 松散耦合 缺点: 效率较低 自定义信号 自定义槽函数是非常关键的&a…

VMware 安装 centos7.9教程

目录 VMware17安包装 1.创建新的虚拟机 2.稍后安装一个系统 3.选择Centos7 4.选择安装位置 5.指定磁盘内存大小 6.自定义硬件 7.编辑内存 8.编辑处理器 9.选择安装镜像位置 10.选择网络适配器 11.播放虚拟机 12.选择语言简体中文 13.选择时区时间 14.最小化安装 …

电机学习-基础知识

文章目录 1 基本物理概念1.1 左手定则1.2 安培定则1.3 感应电动势 2 电机简单分类2.1 直流有刷电机2.2 步进电机2.2.1 步进电机的驱动原理1.相与线2.极性3.步进电机的驱动 2.3 无刷电机2.3.1 充磁方式2.3.2正弦波电动势与梯型电动势 3 编码器3.1 霍尔编码器3.2 光电编码器3.3 增…

TexWorks配置使用latexmk实现增量编译

TexWorks配置使用latexmk实现增量编译 TexWorks默认使用pdfLaTeXMakeIndexBibTeX&#xff0c;修改后&#xff0c;重新编译等待时间较长。本文旨在说明配置TexWorks使用latexmk实现增量式编译&#xff0c;加速编译。 前置条件说明 (1) 通过miktex自动安装了TexWorks及自带pdf…

Docker相关配置记录

Docker相关配置记录 换源 {"registry-mirrors": ["https://dockerhub.icu","https://docker.chenby.cn","https://docker.1panel.live","https://docker.awsl9527.cn","https://docker.anyhub.us.kg","htt…

VisionPro二次开发学习笔记12-使用CogToolGroup控件进行图像检测

本示例演示了如何通过图像数据库使用 CogImageFileTool&#xff0c;并将其放入 CogToolGroup 中&#xff0c;对于数据库中的每个图像运行一次检测. 当用户按下 运行 按钮时&#xff0c;程序执行以下操作&#xff1a; 如果工具组中没有 CogImageFileTools&#xff0c;它将显示一…

Codeforces Pinely Round 4 (Div. 1 + Div. 2) A~G

A.Maximize the Last Element&#xff08;枚举&#xff09; 题意&#xff1a; 给你一个由 n n n个整数组成的数组 a a a&#xff0c;其中 n n n是奇数。 在一次操作中&#xff0c;你将从数组 a a a中删除两个相邻的元素&#xff0c;然后将数组的剩余部分连接起来。例如&…

轻松构建Electron应用:TypeScript与esbuild的完美搭档

简介 使用 TypeScript (TS) 编写 Electron 应用程序带来了许多好处&#xff0c;以下是一些主要优势&#xff1a; 类型安全&#xff1a;TypeScript 是一种静态类型语言&#xff0c;它在编译时检查类型错误&#xff0c;这有助于在开发过程中及早发现潜在的错误。更好的工具支持…