当前位置: 首页 > article >正文

OpenCV——Mat类及常用数据结构

Mat类及常用数据结构

  • 一、Mat类简介
    • 1.1、矩阵头
    • 1.2、矩阵的数据类型
    • 1.3、Mat的子类
  • 二、矩阵数据的存储
    • 2.1、单通道
    • 2.2、多通道
  • 三、创建矩阵的方法
    • 3.1、静态方法创建
    • 3.2、构造方法创建
    • 3.3、读取图像文件创建
    • 3.4、克隆创建
  • 四、获取矩阵信息
  • 五、矩阵相关操作
    • 5.1、获取/修改像素值
    • 5.2、批量获取/修改像素值
  • 六、常用数据结构
    • 6.1、Point类(点)
    • 6.2、Rect类(矩形)
    • 6.3、Size类(尺寸)
    • 6.4、Scalar类(颜色)
    • 6.5、示例

一、Mat类简介

Mat是矩阵类(Matrix)的缩写,Mat由矩阵头(Header)和数据两部分组成。

1.1、矩阵头

矩阵头中包含了矩阵尺寸、存储方法,存储地址等信息。

public class MatDemo {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {Mat m = Mat.zeros(2, 3, CvType.CV_8UC1);//打印矩阵信息System.out.println(m);}
}
Mat [ 2*3*CV_8UC1, isCont=true, isSubmat=false, nativeObj=0x600003f8f060, dataAddr=0x7f7c923071c0 ]
  • 23CV_8UC1:矩阵尺寸是2*3,数据类型是CV_8UC1
  • isCont=true:是否连续存储
  • isSubmat=false:是否为子矩阵(子矩阵指矩阵的一个子区域,子矩阵可以像矩阵一样进行处理和保存,但是对子矩阵的任何修改都会同时影响原来的矩阵)
  • nativeObj=0x600003f8f060:本地对象地址
  • dataAddr=0x7f7c923071c0:存储的图片的地址

1.2、矩阵的数据类型

以CV_8UC3为例:

  • CV表示OpenCV
  • 下划线后由四部分组成:
    • 第一部分表示数据位数,8表示8位,16表示16位,32表示32位,64表示64位
    • 第二部分表示数据类型,U代表无符号整型,S代表有符号整型,F代表浮点类型
    • 第三部分C代表通道
    • 第四部分为通道数:1表示1通道,2表示2通道,3表示3通道
图像深度数字值具体描述取值范围
CV_8U08位无符号整数0~255
CV_8S18位有符号整数-128~127
CV_16U216位无符号整数0~65535
CV_16S316位有符号整数-32768~32767
CV_32S432位有符号整数-2147483~2147483647
CV_32F532位浮点数-
CV_64F664位浮点数-

1.3、Mat的子类

Mat类可以存储哥哥不同的数据类型。根据数据类型的不同,Mat类又派生出多个子类。
在这里插入图片描述

二、矩阵数据的存储

2.1、单通道

Mat类存储图像数据时,可以看做按照栅格扫描顺序存储的数组。单通道的灰度图中数据的排列顺序如下:

11列的灰度值 12列的灰度值 13列的灰度值...
21列的灰度值 22列的灰度值 23列的灰度值...
31列的灰度值 32列的灰度值 33列的灰度值...
...

举例,3*3大小8位1通道的灰度图存储如下

public class MatDemo {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {Mat m = Mat.zeros(3, 3, CvType.CV_8UC1);//打印矩阵内部存储System.out.println(m.dump());}
}
1通道,所以同一行1个值表示1个像素点
[  0,   0,   0;0,   0,   0;0,   0,   0]

2.2、多通道

灰度图因为只有一个通道,所以相对简单,3个通道的RGB彩色图像在OpenCV中颜色是按B(蓝色)、G(绿色)、R(红色)的顺序排列的。3*3大小8位3通道的存储如下:

public class MatDemo {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {Mat m = Mat.zeros(3, 3, CvType.CV_8UC3);//打印矩阵内部存储System.out.println(m.dump());}
}
3通道,所以13个值表示一个像素点第一行	         		第二行          	   第三行 
[  0(B),0(G),0(R),		0,   0,   0,   		0,   0,   0;    第一列0,   0,   0,   		0,   0,   0,   		0,   0,   0;	第二列0,   0,   0,   		0,   0,   0,   		0,   0,   0]	第三列

三、创建矩阵的方法

3.1、静态方法创建

public class CreateMat {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//创建2*3全为0的矩阵Mat m1 = Mat.zeros(2, 3, CvType.CV_8UC1);System.out.println(m1.dump());//创建2*3全为1的矩阵Mat m2 = Mat.ones(2, 3, CvType.CV_8UC1);System.out.println(m2.dump());//创建3*3的矩阵,当行号等于列号时值为1,其余值为0Mat m3 = Mat.eye(3, 3, CvType.CV_8UC1);System.out.println(m3.dump());//需要注意的是,如果通道数大于1,则onces()创建的Mat类只有第一个通道的值为1Mat m4 = Mat.ones(3, 3, CvType.CV_8UC3);System.out.println(m4.dump());}
}
[  0,   0,   0;0,   0,   0]
[  1,   1,   1;1,   1,   1]
[  1,   0,   0;0,   1,   0;0,   0,   1]
[  1,   0,   0,   1,   0,   0,   1,   0,   0;1,   0,   0,   1,   0,   0,   1,   0,   0;1,   0,   0,   1,   0,   0,   1,   0,   0]

3.2、构造方法创建

在这里插入图片描述

这14种方法大多类似,下面介绍最常用的几种:

//构造方式创建
//方法一
Mat mat1 = new Mat();
mat1.create(3, 3, CvType.CV_8UC1);//方法二
Mat src = Mat.ones(2, 2, CvType.CV_8UC1);
Mat dst = new Mat();
src.copyTo(dst);//将src复制到dst//方法三
//大小为100*100,8位3通道蓝色
Mat mat = new Mat(100, 100, CvType.CV_8UC3, new Scalar(255, 0, 0));

3.3、读取图像文件创建

//读取文件创建
Mat fish = Imgcodecs.imread("/Users/acton_zhang/J2EE/MavenWorkSpace/opencv_demo/src/main/java/demo1/fish.png");
//在频幕显示图像
HighGui.imshow("fish", fish);
//按任意键退出
HighGui.waitKey();

3.4、克隆创建

Mat src = Mat.ones(2, 2, CvType.CV_8UC1);
Mat dst - src.clone();

四、获取矩阵信息

public class GetMatInfo {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {Mat fish = Imgcodecs.imread("/Users/acton_zhang/J2EE/MavenWorkSpace/opencv_demo/src/main/java/demo1/fish.png");//获取矩阵头System.out.println(fish);//获取矩阵行数System.out.println(fish.rows());//获取矩阵列数System.out.println(fish.cols());//获取矩阵维度,2*3为二维,3*3*5为3维System.out.println(fish.dims());//获取矩阵通道数System.out.println(fish.channels());//获取矩阵的深度System.out.println(fish.depth());//获取矩阵的尺寸System.out.println(fish.size());//获取矩阵的数据类型System.out.println(fish.type());//获取矩阵元素个数,等于行*列System.out.println(fish.total());//获取矩阵数据//System.out.println(fish.dump());}
}
Mat [ 750*998*CV_8UC3, isCont=true, isSubmat=false, nativeObj=0x6000025045a0, dataAddr=0x7fbf66a4b000 ]
750
998
2
3
0
998x750
16
748500

五、矩阵相关操作

5.1、获取/修改像素值

获取像素值使用get方法:

  • int Mat.get(int row, int col, byte[] data)
  • int Mat.get(int row, int col, short[] data)
  • int Mat.get(int row, int col, int[] data)
  • int Mat.get(int row, int col, float[] data)
  • int Mat.get(int row, int col, double[] data)

注意:当row和col为0时表示第一行第一列。Java中的byte类型取值范围为-128~127,如果矩阵数据类型为CV_8U,则二者取值范围并不一致。

修改像素值使用put方法:

  • int Mat.put(int row, int col, byte[] data)
  • int Mat.put(int row, int col, short[] data)
  • int Mat.put(int row, int col, int[] data)
  • int Mat.put(int row, int col, float[] data)
  • int Mat.put(int row, int col, double[] data)
public class MatPixel {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {Mat m = Mat.eye(3, 3, CvType.CV_8UC1);//输出修改前的矩阵数据System.out.println(m.dump());System.out.println();//将第二行第二列值改为9m.put(1, 1, 9);//输出修改后的矩阵数据System.out.println(m.dump());System.out.println();//获取第二行第二列的像素值,存储在data数组中byte[] data = new byte[1];//单通道,所以数组长度为1即可m.get(1, 1, data);//输出像素值System.out.println(data[0]);}
}
[  1,   0,   0;0,   1,   0;0,   0,   1][  1,   0,   0;0,   9,   0;0,   0,   1]9

上述程序有个潜在问题,矩阵m的数据类型和data数组的数据类型并不匹配。如果put(1,1, 255),则超过了byte的上限,修改后代码如下:

public class MatPixel {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {Mat m = Mat.eye(3, 3, CvType.CV_32SC1);//修改为32位整型//输出修改前的矩阵数据System.out.println(m.dump());System.out.println();//将第二行第二列值改为9m.put(1, 1, 255);//输出修改后的矩阵数据System.out.println(m.dump());System.out.println();//获取第二行第二列的像素值,存储在data数组中int[] data = new int[1];//单通道,所以数组长度为1即可m.get(1, 1, data);//输出像素值System.out.println(data[0]);}
}
[1, 0, 0;0, 1, 0;0, 0, 1][1, 0, 0;0, 255, 0;0, 0, 1]255

看上去问题得到了解决,但是实际上还存在一个问题,矩阵的数据类型为CV_32SC1,不是希望的CV_8UC1。要彻底解决这个问题,需要调用Mat类的convertTo()方法。

5.2、批量获取/修改像素值

如果将get/put方法的行号和列号都置为0,同时第三个参数数组足够大,则可以用于批量获取或修改数据。

public class MatPixel {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {Mat m = Mat.eye(2, 2, CvType.CV_32SC3);//将矩阵数据存放在数据data中int[] data = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 200, 255};//批量修改矩阵数据m.put(0, 0, data);//查看矩阵数据System.out.println(m.dump());System.out.println();//转化矩阵数据类型Mat mat = new Mat();m.convertTo(mat, CvType.CV_8SC3);//获取矩阵的所有数据int[] i = new int[12];//获取所有数据m.get(0, 0, i);//查看mat的矩阵头System.out.println(mat);System.out.println();//查看矩阵数据System.out.println(mat.dump());System.out.println();//查看数组i的数据for (int n = 0; n < i.length; n++) {System.out.print(i[n] + ",");}}
}
[1, 2, 3, 4, 5, 6;7, 8, 9, 128, 200, 255]Mat [ 2*2*CV_8SC3, isCont=true, isSubmat=false, nativeObj=0x600002436d00, dataAddr=0x7fc463805040 ][  1,   2,   3,   4,   5,   6;7,   8,   9, 127, 127, 127]1,2,3,4,5,6,7,8,9,128,200,255,

六、常用数据结构

6.1、Point类(点)

Point类用于表示二维坐标系中的一个点。成员变量为x,y。

Point(double x, double y)
x:点的x坐标
y:点的y坐标

6.2、Rect类(矩形)

Rect类用于表示一个矩形,成员变量为x,y,width和height。

Rect(int x, int y, int width, int height)
x:左上角顶点x坐标
y:左上角顶点y坐标
width:矩形宽度
height:矩形高度

6.3、Size类(尺寸)

Size类用于表示尺寸,成员变量为width,height。

Size(double width, double height)
width:宽度
height:高度

6.4、Scalar类(颜色)

Scalar表示具有4个元素的数组,在OpenCV中被用来传递颜色值,如RGB的色彩值。Scalar表示颜色时的顺序是B(蓝色)、G(绿色)、R(红色),如果是四通道,则在后面跟透明度。

Scalar(double v0)
通常用于构造灰度图像
v0:灰度值Scalar(double v0, double v1, double v2);
通常用于三通道图像v0:B值
v1:G值
v2:RScalar(double v0, double v1, double v2, double v3);
通常用于四通道图像v0:B值
v1:G值
v2:R值
v3:透明度值

6.5、示例

public class BaseStructure {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//创建PointPoint p = new Point(10, 20);System.out.println(p);System.out.println(p.x + "," + p.y);System.out.println();//创建RectRect r = new Rect(10, 20, 50, 100);System.out.println(r);System.out.println(r.x + "," + r.y + "," + r.width + "," + r.height);System.out.println();//创建SizeSize s = new Size(50, 100);System.out.println(s);System.out.println(s.width + "," + s.height);System.out.println();//创建ScalarScalar red = new Scalar(0, 0, 255);System.out.println(red);System.out.println();}
}
{10.0, 20.0}
10.0,20.0{10, 20, 50x100}
10,20,50,10050x100
50.0,100.0[0.0, 0.0, 255.0, 0.0]

相关文章:

OpenCV——Mat类及常用数据结构

Mat类及常用数据结构 一、Mat类简介1.1、矩阵头1.2、矩阵的数据类型1.3、Mat的子类 二、矩阵数据的存储2.1、单通道2.2、多通道 三、创建矩阵的方法3.1、静态方法创建3.2、构造方法创建3.3、读取图像文件创建3.4、克隆创建 四、获取矩阵信息五、矩阵相关操作5.1、获取/修改像素…...

深入解析FutureTask:原理与实战

我们来深入解析 FutureTask。下面将从它们的用法开始&#xff0c;逐步深入到底层实现、方法和接口设计&#xff0c;并探讨它们对于我们自己设计实现以及其他编程实践的学习意义。 主要就是放入等待队列&#xff08;CAS操作一个链表头&#xff09;&#xff0c;完成任务的线程唤…...

每天总结一个html标签——Audio音频标签

Audio标签 文章目录 Audio标签一、audio标签的定义与介绍1. 定义介绍2. 语法3. 支持的格式4.文本提示 二、audio标签的HTML属性1. autoplay2. loop3. muted4. preload 三、audio标签的常用DOM属性四、audio标签的常用事件四、默认样式五、自定义样式1. 示例2. 代码 六、播放 m3…...

使用 React Native 开发鸿蒙(HarmonyOS)运动健康类应用的系统化准备工作

⚙️ ​​一、环境与工具准备​​ ​​双环境搭建​​ ​​React Native 环境​​&#xff1a;安装 Node.js&#xff08;≥18.x&#xff09;、JDK&#xff08;≥11&#xff09;、Yarn。​​鸿蒙开发环境​​&#xff1a; 下载 DevEco Studio 4.0 及 HarmonyOS SDK&#xff1b;配…...

web3-Remix部署智能合约到“荷兰式”拍卖及以太坊gas费机制细讲

web3-Remix部署智能合约到“荷兰式”拍卖及以太坊gas费机制细讲 一、使用Remix演示智能合约部署 智能合约的代码编写一般都是在Remix上&#xff0c;Remix的好处的话就是可以在浏览器中快速开发和部署合约&#xff0c;无需在本地安装任何程序&#xff0c;十分适合新手。 对应…...

网络编程及原理(一)

目录 一 . 独立模式与网络互联 二 . 局域网 —— LAN &#xff08;1&#xff09;基于网线直连 &#xff08;2&#xff09;基于集线器组建 &#xff08;3&#xff09;基于交换机组建 &#xff08;4&#xff09;基于交换机和路由器组建 三 . 广域网 —— WAN 四 …...

superior哥AI系列第9期:高效训练与部署:从实验室到生产环境

&#x1f680; superior哥AI系列第9期&#xff1a;高效训练与部署&#xff1a;从实验室到生产环境 嘿&#xff01;小伙伴们&#xff01;&#x1f44b; 欢迎来到superior哥AI系列第9期&#xff01;经过前面8期的学习&#xff0c;你已经掌握了深度学习的核心技术。但是&#xff0…...

【Linux】进程 信号保存 信号处理 OS用户态/内核态

&#x1f33b;个人主页&#xff1a;路飞雪吖~ &#x1f320;专栏&#xff1a;Linux 目录 一、信号保存 ✨进程如何完成对信号的保存&#xff1f; ✨在内核中的表示 ✨sigset_t ✨信号操作函数 &#x1fa84;sigprocmask --- 获取或设置当前进程的 block表 &#x1fa84;s…...

[ Qt ] | 与系统相关的操作(一):鼠标相关事件

目录 信号和事件的关系 (leaveEvent和enterEvent) 实现通过事件获取鼠标进入和鼠标离开 (mousePressEvent) 实现通过事件获得鼠标点击的位置 (mouseReleaseEvent) 前一个的基础上添加鼠标释放事件 (mouseDoubleClickEvent) 鼠标双击事件 鼠标移动事件 鼠标滚轮事件 …...

stm32使用hal库模拟spi模式3

因为网上模拟spi模拟的都是模式0&#xff0c;很少有模式3的。 模式3的时序图&#xff0c;在clk的下降沿切换电平状态&#xff0c;在上升沿采样&#xff0c; SCK空闲为高电平 初始化cs&#xff0c;clk&#xff0c;miso&#xff0c;mosi四个io。miso配置为输入&#xff0c;cs、c…...

安装 Nginx

个人博客地址&#xff1a;安装 Nginx | 一张假钞的真实世界 对于 Linux 平台&#xff0c;Nginx 安装包 可以从 nginx.org 下载。 Ubuntu: 版本Codename支持平台12.04precisex86_64, i38614.04trustyx86_64, i386, aarch64/arm6415.10wilyx86_64, i386 在 Debian/Ubuntu 系统…...

Vue-1-前端框架Vue基础入门之一

文章目录 1 Vue简介1.1 Vue的特性1.2 Vue的版本2 Vue的基础应用2.1 Vue3的下载2.2 Vue3的新语法2.3 vue-devtools调试工具3 Vue的指令3.1 内容渲染指令{{}}3.2 属性绑定指令v-bind3.3 事件绑定指令v-on3.4 双向绑定指令v-model3.5 条件渲染指令v-if3.6 列表渲染指令v-for4 参考…...

OurBMC技术委员会2025年二季度例会顺利召开

5月28日&#xff0c;OurBMC社区技术委员会二季度例会顺利召开。本次会议采用线上线下结合的方式&#xff0c;各委员在会上听取了OurBMC社区二季度工作总结汇报&#xff0c;规划了2025年三季度的重点工作。 会上&#xff0c;技术委员会主席李煜汇报了社区2025年二季度主要工作及…...

postman自动化测试

目录 一、相关知识 1.网络协议 2.接口测试 3.编写测试用例 4.系统架构 二、如何请求 1.get请求 ​编辑2.post请求 3.用环境变量请求 4.Postman测试沙箱 一、相关知识 1.网络协议 规定数据信息发送与解析的方式。 网络传输协议 https相比http&#xff0c;信息在网…...

力扣热题100之二叉树的直径

题目 给你一棵二叉树的根节点&#xff0c;返回该树的 直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。 两节点之间路径的 长度 由它们之间边数表示。 代码 方法&#xff1a;递归 计算二叉树的直径可以理解…...

数字人技术的核心:AI与动作捕捉的双引擎驱动(210)

**摘要&#xff1a;**数字人技术从静态建模迈向动态交互&#xff0c;AI与动作捕捉技术的深度融合推动其智能化发展。尽管面临表情僵硬、动作脱节、交互机械等技术瓶颈&#xff0c;但通过多模态融合技术、轻量化动捕方案等创新&#xff0c;数字人正逐步实现自然交互与情感表达。…...

c++ 命名规则

目录 总结1. 类名&#xff08;Class Names&#xff09;2. 变量名&#xff08;Variable Names&#xff09;3. 函数名&#xff08;Function Names&#xff09;4. 宏定义&#xff08;Macros&#xff09;5. 命名空间&#xff08;Namespaces&#xff09;6. 枚举&#xff08;Enums&am…...

GRU 参数梯度推导与梯度消失分析

GRU 参数梯度推导与梯度消失分析 1. GRU 前向计算回顾 GRU 单元的核心计算步骤&#xff08;忽略偏置项&#xff09;&#xff1a; 更新门: z_t σ(W_z [h_{t-1}, x_t]) 重置门: r_t σ(W_r [h_{t-1}, x_t]) 候选状态: ̃h_t tanh(W_h [r_t ⊙ h_{t-1}, x_t]) 新…...

针对KG的神经符号集成综述 两篇

帖子最后有五篇综述的总结。 综述1 24年TKDD 系统性地概述了神经符号知识图谱推理领域的进展、技术和挑战。首先介绍了知识图谱&#xff08;KGs&#xff09;和符号逻辑的基本概念&#xff0c;知识图谱被视为表示、存储和有效管理知识的关键工具&#xff0c;它将现实世界的知识…...

RabbitMQ和MQTT区别与应用

RabbitMQ与MQTT深度解析&#xff1a;协议、代理、差异与应用场景 I. 引言 消息队列与物联网通信的重要性 在现代分布式系统和物联网&#xff08;IoT&#xff09;生态中&#xff0c;高效、可靠的通信机制是构建稳健、可扩展应用的核心。消息队列&#xff08;Message Queues&am…...

Vue跨层级通信

下面,我们来系统的梳理关于 Vue跨层级通信 的基本知识点: 一、跨层级通信核心概念 1.1 什么是跨层级通信 跨层级通信是指在组件树中,祖先组件与后代组件(非直接父子关系)之间的数据传递和交互方式。这种通信模式避免了通过中间组件层层传递 props 的繁琐过程。 1.2 适用…...

docker常见命令行用法

&#x1f9e8; 一、关闭和清理 Docker 服务相关命令 &#x1f53b; docker-compose down 作用&#xff1a;关闭并删除所有使用当前 docker-compose.yml 启动的容器、网络、挂载卷&#xff08;匿名的&#xff09;、和依赖关系。 通俗解释&#xff1a;就像你关掉了一个 App&am…...

Axure设计案例:滑动拼图解锁

设计以直观易懂的操作方式为核心&#xff0c;只需通过简单的滑动动作&#xff0c;将拼图块精准移动至指定位置&#xff0c;即可完成解锁。这种操作模式既符合用户的日常操作习惯&#xff0c;在视觉呈现上&#xff0c;我们精心设计拼图图案&#xff0c;融入生动有趣的元素&#…...

MySQL权限详解

在MySQL中&#xff0c;权限管理是保障数据安全和合理使用的重要手段。MySQL提供了丰富的权限控制机制&#xff0c;允许管理员对不同用户授予不同级别的操作权限。本文将会对MySQL中的权限管理&#xff0c;以及内核如何实现权限控制进行介绍。 一、权限级别 MySQL 的权限是分层…...

基于BP神经网络的语音特征信号分类

基于BP神经网络的语音特征信号分类的MATLAB实现步骤&#xff1a; 1. 数据预处理 信号采样&#xff1a;读取语音信号并进行采样&#xff0c;确保信号具有统一的采样率。例如&#xff1a; [y, Fs] audioread(audio_file.wav); % 读取音频文件预加重&#xff1a;增强高频信号&am…...

解决fastadmin、uniapp打包上线H5项目路由冲突问题

FastAdmin 基于 ThinkPHP&#xff0c;默认采用 URL 路由模式&#xff08;如 /index.php/module/controller/action&#xff09;&#xff0c;且前端资源通常部署在公共目录&#xff08;如 public/&#xff09;下。Uniapp 的历史模式需要将所有前端路由请求重定向到 index.html&a…...

web3-区块链的交互性以及编程的角度看待智能合约

web3-区块链的交互性以及编程的角度看待智能合约 跨链交互性 交互性 用户在某一区块链生态上拥有的资产和储备 ​ 目标&#xff1a;使用户能够把资产和储备移动到另一个区块链生态上 可组合性 使在某一区块链的DAPP能调用另一个区块链上的DAPP 如果全世界都在用以太坊就…...

数据结构(7)—— 二叉树(1)

目录 前言 一、 树概念及结构 1.1树的概念 1.2树的相关概念 1.3数的表示 1.二叉树表示 2.孩子兄弟表示法 3.动态数组存储 1.4树的实际应用 二、二叉树概念及结构 2.1概念 2.2特殊的二叉树 1.满二叉树 2. 完全二叉树 2.3二叉树的性质 2.4二叉树的存储结构 1.顺序存储 2.链式存储…...

ROS1和ROS2的区别autoware.ai和autoware.universe的区别

文章目录 前言一、ROS1和ROS2的区别一、ROS2通讯实时性比ROS1强二、ROS1官方不再维护了三、ROS2的可靠性比ros1强四、ROS2的安全性比ros1强五、ROS2资源占用低六、等等等等 二、autoware.ai和autoware.universe的区别一、autoware.ai不维护了二、autoware.universe功能多&#…...

如何使用 Docker 部署grafana和loki收集vllm日志?

环境: Ubuntu20.04 grafana loki 3.4.1 问题描述: 如何使用 Docker 部署grafana和loki收集vllm日志? 解决方案: 1.创建一个名为 loki 的目录。将 loki 设为当前工作目录: mkdir loki cd loki2.将以下命令复制并粘贴到您的命令行中,以将 loki-local-config.yaml …...