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

OpenCV 笔记(4):图像的算术运算、逻辑运算

Part11.  图像的算术运算

图像的本质是一个矩阵,所以可以对它进行一些常见的算术运算,例如加、减、乘、除、平方根、对数、绝对值等等。除此之外,还可以对图像进行逻辑运算和几何变换。

我们先从简单的图像加、减、逻辑运算开始介绍。后续会有专门的内容介绍图像的几何变换等。

11.1 图像加法

图像的加法是将两个大小、类型相同的图像按照逐个像素进行相加,最后得到一个新的图像。

图像的加、减、乘、除运算,都是两个大小、类型相同的图像进行运算。

1.1.1 加法的例子

图像相加的公式:

也可以使用:dst += src1,其中 += 是 C++ 可重载的运算符。

举个简单的例子:

Mat a = imread(".../cat.jpg");// 加载了一张猫的图片
imshow("a", a);Mat b = Mat(Size(a.cols,a.rows),a.type(), Scalar(0,0,255));// 生成跟a大小类型一样,红色的图像Mat c;
cv::add(a,b,c);// 将 a、b 相加,结果为c
imshow("c", c);
e652cd2c39032b9a33d8980d6cbfc7f3.jpeg
add.png

上述代码中 Mat 对象 c 是 Mat 对象 a、b 相加得到的产物。如果将 b 改成白色也就是 Scalar(255,255,255)。那么 c 会变成什么呢?答案依然是白色。因为加法是像素相加,如果两个像素点超出255,那么依旧会变成255。

1.1.2 实现 add() 函数的功能

为了解释上面的问题,我们尝试自己实现一个 add 函数的功能。

Mat a = imread(".../cat.jpg"); // 加载 cat 的图像
imshow("a", a);Mat b = Mat(Size(a.cols,a.rows),a.type(), Scalar(0,0,255));int h = a.rows; // 图像 a 的高
int w = a.cols; // 图像 a 的宽Mat c = Mat::zeros(a.size(), a.type());
for (int row = 0; row < h; row++)
{for (int col = 0; col < w; col++){Vec3b p1 = a.at<Vec3b>(row, col);Vec3b p2 = b.at<Vec3b>(row, col);c.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(p1[0] + p2[0]);c.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(p1[1] + p2[1]);c.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(p1[2] + p2[2]);}
}imshow("c", c);

通过2层for循环遍历 a、b 图像的每个像素点,并将结果相加赋值给 c 图像对应的像素点。在相加的时候,使用了 saturate_cast() 函数。

saturate_cast() 是一个模版函数,它的作用是防止溢出。它支持 uchar、short、int、float、double 等各种类型。

对于 uchar 类型,如果像素值超过255,使用 saturate_cast() 函数后它的值变为255。这也正好解释了,如果 b 是白色,那么最终得到的 c 对象也会是白色。

1.1.3 使用 copyTo() 函数实现的图像叠加

前面的文章我们曾介绍过 copyTo() 函数,它可以将 Mat 对象拷贝到另一个 Mat 对象上。

现在再来回顾一下它的使用

Mat a = imread(".../cat.jpg"); // 加载 cat 的图像Mat b = imread(".../leaf.png"); // 加载一张小尺寸的树叶的图像Mat roi = a(Rect(0,0,b.cols,b.rows));b.copyTo(roi);imshow("result", a);

在上述代码中, roi 对象是从 a 对象中截取一块区域,并且该区域跟 b 对象大小一样。由于提取 roi 的操作是浅拷贝,将 b 对象复制到 roi 对象之后,就会改变 a 对象本身。

下面是执行的结果:

2c569c933cc58502bd1382c73856cddc.jpeg
copyTo.png

因此,可以借助 copyTo() 函数来实现图像的叠加。

21.2 图像的线性混合(linear blending)

图像的线性混合公式:$$dst = src1alpha + src2beta + gamma$$

其中,alpha、beta 分别表示图像1和图像2的权重,gamma 是亮度调节量。当 alpha = beta = 1 且 gamma = 0 时,表示两个图像的相加。

进行线性混合的两个图像,也必须大小和类型一致。

Mat a = imread(".../cat.jpg"); // 加载 cat 的图像Mat b = imread(".../chinese_flag.png"); // 加载五星红旗的图像resize(a, a,Size(b.cols,b.rows));// 缩放a的大小,跟b保持一致Mat dst;
addWeighted(a, 0.5, b, 0.5,0, dst);imshow("dst", dst);

由于图像 a、b 大小不一样,因此在线性混合之前需要用 resize() 函数将图像 a 的大小按照图像 b 的大小进行缩放。

02db30447a3998ea6c3028b4dd52adcd.jpeg
linear_lending.png

上面的代码,将猫和五星红旗完成了线性混合。如果还想尝试做一个国庆版本的渐变头像,则需要离红旗越近,红旗的权重越大。

我们可以这样写代码:

Mat a = imread(".../cat.jpg"); // 加载 cat 的图像Mat flag = imread(".../chinese_flag.png");
int flag_width = flag.cols;
int flag_height = flag.rows;Mat dst;resize(a, dst, Size(flag_width, flag_height));int radius = 0;
if (flag_width > flag_height) {radius = flag_width;
} else {radius = flag_height;
}for (int i=0; i < dst.rows; i++) {for (int j=0; j < dst.cols; j++) {int distance = std::sqrt(i*i+j*j);double alpha;if (distance > radius) {alpha =  1;}  else {alpha = (double) distance / radius;}double beta = 1 - alpha;Vec3b v1 = dst.at<Vec3b>(i, j);dst.at<Vec3b>(i, j)[0]= alpha * v1[0] + beta * flag.at<Vec3b>(i, j)[0];dst.at<Vec3b>(i, j)[1]= alpha * v1[1] + beta * flag.at<Vec3b>(i, j)[1];dst.at<Vec3b>(i, j)[2]= alpha * v1[2] + beta * flag.at<Vec3b>(i, j)[2];}
}imshow("dst", dst);
b5c58c05ccebdee7f367b9164b981ae0.jpeg
avatar.png

31.3 图像减法

图像相减是两个图像按照逐个像素进行相减,图像相减可以检测出两个图像的差异。利用这个差异可以做各种检测,因此图像减法在很多领域都有实际的用途。

图像相减的公式:

也可以使用:dst -= src1,其中 -= 是 C++ 可重载的运算符。

举个简单的例子:

Mat a = imread(".../cat.jpg"); // 加载 cat 的图像int width = a.cols;
int height = a.rows;Mat b = Mat(Size(width,height), a.type(),Scalar(0,0,0));
circle(b, Point(width/2, height/2), 600, Scalar(255,255,255), -1);Mat dst;
subtract(a,b,dst);imshow("dst", dst);
ab81bd140cefb86fb98759a9a6c67dae.jpeg
subtract.png

上述执行的结果是图像 a 减去图像 b 之后得到的结果,将中间的猫“抠掉”了。如果只想要中间的猫,而不要背景该怎么做呢?本文后续会用 bitwise_and 运算来获取。

再举个例子,对加载图像进行高斯模糊,然后用原图减去高斯模糊后的图,会得到两张图像的差异。

Mat a = imread(".../cat.jpg"); // 加载 cat 的图像
imshow("a",a);Mat b;
GaussianBlur(a, b,Size(15,15),0,0);
imshow("b",b);Mat dst;
subtract(a,b,dst);
imshow("dst",dst);
15eab01ffd75bb6cb5a6b10e2c8c89db.jpeg
diff.png

图像的减法介绍完之后,图像的乘法(multiply)、除法(divide)、差的绝对值(absdiff)的用法都很类似,在实际工作中也经常会用到。特别是 absdiff() 函数,用公式表示:

可以用它获取 差分图,经常应用在视频分析中。

Part22. 图像的逻辑运算

42.1 掩模的基础知识

在介绍图像的逻辑运算之前,再来回顾一下掩模(mask)的知识,因为 OpenCV 很多的函数中都会用到 mask 这个参数。

图像的算术运算、逻辑运算都支持 mask。

掩模是小于或等于源图像的单通道矩阵,掩模中的值分为 0 和非 0。

图像掩模是用选定的图像、图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。

掩模的作用:

  • 提取 ROI

  • 屏蔽作用

  • 提取结果特征

  • 制作特殊形状的图像

掩模的生成方式有很多种。

我们可以自己创建一个,将图像减法的第一个例子图像 b 稍微改一下即可。因为 mask 是单通道的矩阵。

Mat mask = Mat(Size(width,height), CV_8UC1,Scalar(0,0,0));
circle(mask, Point(width/2, height/2), 600, Scalar(255,255,255), -1);

我们也可以通过图像二值化阈值分割来提取 mask,例如:

Mat src = imread(".../leaf.png"); // 加载一张小尺寸的树叶的图像
imshow("src",src);Mat gray;
cvtColor(src,gray,COLOR_BGR2GRAY);Mat mask;
threshold(gray, mask, 0, 255, THRESH_BINARY_INV|THRESH_OTSU);imshow("mask",mask);
f8b06902fdb95bc438ddf363532a8033.jpeg
mask.png

图像二值化的相关内容后续文章会专门介绍。总之,mask 的制作有很多方式。

52.2 逻辑运算

两个图像可以进行与、或、异或等逻辑运算。下面是逻辑操作的真值表:

aba AND ba OR ba XOR bNOT a
000001
010111
100110
111100

其中,

  • 与运算的原理:如果 a、b 两个值有0,则与的结果为0;如果 a、b 全为1,则与的结果为1。

  • 或运算的原理:如果 a、b 两个值有1,则或的结果为1;如果 a、b 全为0,则与或的结果为0。

  • 异或运算的原理:如果 a、b 两个值不相同,则异或结果为1;如果 a、b 两个值相同,则异或结果为0。

  • 非运算的原理:如果 a 的值为1,则非运算的结果为0;如果 a 的值为0,则非运算的结果为1。

图像的逻辑运算也需要两个大小、类型相同的图像才能进行运算。

Mat a = imread(".../cat.jpg"); // 加载 cat 的图像Mat b = Mat(Size(a.cols,a.rows),a.type(), Scalar(0,0,255));// 生成跟a大小类型一样,红色的图像Mat dst1,dst2,dst3,dst4;
bitwise_and(a,b,dst1);
bitwise_or(a,b,dst2);
bitwise_xor(a,b,dst3);
bitwise_not(a,dst4);imshow("bitwise_and", dst1);
imshow("bitwise_or", dst2);
imshow("bitwise_xor", dst3);
imshow("bitwise_not", dst4);
92cff44b254575d5858af9a7b2dc1069.jpeg
bitwise_op.png

OpenCV 中的逻辑与、或、异或、非运算对应的函数分别是 bitwise_and、bitwise_or、bitwise_xor、bitwise_not。上图也分别展示了这些函数的执行结果。

现在我们来回答一下前面的问题,如何只“抠掉”中间的猫?答案是只要使用 bitwise_and 函数即可。

Mat a = imread(".../cat.jpg"); // 加载 cat 的图像int width = a.cols;
int height = a.rows;Mat b = Mat(Size(width,height), a.type(),Scalar(0,0,0));
circle(b, Point(width/2, height/2), 600, Scalar(255,255,255), -1);Mat dst;
bitwise_and(a,b,dst);
imshow("dst", dst);
cfbcdfe246fa305478844a28507a2989.jpeg
bitwise_and.png

62.3 利用 mask 进行图像融合

对刚才的代码稍微改动一下,把图像 b 的类型改成 CV_8UC1 之后,并改名成 mask。bitwise_and 函数的使用也稍作调整。当 mask 参与 bitwise_and 运算的时候,执行的结果跟刚才是一致的。

Mat a = imread(".../cat.jpg"); // 加载 cat 的图像int width = a.cols;
int height = a.rows;Mat mask = Mat(Size(width,height), CV_8UC1,Scalar(0,0,0));
circle(mask, Point(width/2, height/2), 600, Scalar(255,255,255), -1);Mat dst;
bitwise_and(a,a, dst,mask);
imshow("dst", dst);

因为,当 bitwise_and 函数使用 mask 参数时,该运算只会在掩模值非空的像素点执行。所以可以用来去除背景提取 ROI。

利用 mask 进行“逻辑与”运算,即掩膜图像白色区域是对需要处理图像像素的保留,黑色区域则是对需要处理图像像素的剔除,其余逻辑操作原理类似只是效果不同而已。

之前使用 copyTo() 函数实现的图像叠加生成的图片,效果并不理想,因为树叶不是透明的。

下面,尝试一下将两张图像完美的融合。

Mat a = imread(".../cat.jpg"); // 加载 cat 的图像Mat b = imread(".../leaf.png"); // 加载一张小尺寸的树叶的图像Mat b2gray;
cvtColor(b,b2gray,COLOR_BGR2GRAY); // 对 b 转换成灰度图像
imshow("b2gray", b2gray);Mat mask,mask_inv;
threshold(b2gray, mask, 0, 255, THRESH_BINARY_INV|THRESH_OTSU);// 二值分割获取 mask
imshow("mask", mask);bitwise_not(mask,mask_inv);
imshow("mask_inv", mask_inv);Mat roi = a(Rect(0,0,b.cols,b.rows));
Mat fg,bg;
bitwise_and(roi,roi,bg, mask_inv);
imshow("bg", bg); // 提取 roi 的背景
bitwise_and(b,b,fg,mask);
imshow("fg", fg); // 提取 b 的前景Mat dst;
add(bg,fg,dst);
dst.copyTo(roi);imshow("result", a);

首先加载两张图像,分别为 a、b 对象。

将 b 对象转换成灰度图像,然后通过二值分割获取 mask,以及对 mask 进行非运算获得 mask_inv。

对 a 对象进行截取 roi 的操作,roi 的大小跟 b 对象一致。

然后分别用 与运算 提取 roi 的背景和 b 对象的前景。将两者相加,并将结果拷贝到 roi 对象上。最后,我们可以看到两张图像完美融合的结果。

下面的几张图分别展示了代码中各个阶段生成的对象,以及最后的结果。

e71b5480bcd394a135c84945cd0ae50f.jpeg
step1.png
4fa4e3ed656152439725791737731ace.jpeg
step2.png
3ee7cc086c684619ad80dbefbb72d40f.jpeg
result.png

Part33. 总结

本文分成两个部分。第一部分介绍了图像的算术运算,主要是介绍了图像加法、减法以及它们的实现原理和使用场景,还介绍了图像的线性混合。

第二部分介绍了图像的逻辑运算,回顾了 mask 的用途,以及如何在 bitwise_and 函数中使用 mask。

相关文章:

OpenCV 笔记(4):图像的算术运算、逻辑运算

Part11. 图像的算术运算 图像的本质是一个矩阵&#xff0c;所以可以对它进行一些常见的算术运算&#xff0c;例如加、减、乘、除、平方根、对数、绝对值等等。除此之外&#xff0c;还可以对图像进行逻辑运算和几何变换。 我们先从简单的图像加、减、逻辑运算开始介绍。后续会有…...

创建ABAP数据库表和ABAP字典对象-使用已存在的数据元素增加城市字段04

基于内置域增加一个字段 1.在编辑器中&#xff0c;输入字段的名称&#xff0c;后跟冒号:city:。暂时忽略这个错误。2. 输入/MOC/C并使用自动补全(**Ctrl空格**)&#xff0c;输入类型。3. 然后添加一个分号:city: /moc/city;4.在SAP GUI中查看&#xff0c;字段已经新增...

Centos7上安装 Node.js

文章目录 一、前言二、步骤三、涉及nodejs&#xff0c;centos还是少用吧 一、前言 centos7安装nodejs如果直接安装较高版本会包错误&#xff0c;无法运行npm node: /lib64/libm.so.6: version GLIBC_2.27‘ not found (required by node)二、步骤 网上说的下载升级编译器的方…...

栈及其栈的模拟实现和使用

1. 栈(Stack) 1.1 概念 栈 &#xff1a;一种特殊的线性表&#xff0c;其 只允许在固定的一端进行插入和删除元素操作 。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO &#xff08; Last In First Out &#xff09;的原则…...

HarmonyOS开发:开源一个刷新加载组件

前言 系统Api中提供了下拉刷新组件Refresh&#xff0c;使用起来也是非常的好用&#xff0c;但是风格和日常的开发&#xff0c;有着巨大的出入&#xff0c;效果如下&#xff1a; 显然上面的效果是很难满足我们实际的需求的&#xff0c;奈何也没有提供的属性可以更改&#xff0c;…...

XSSFWorkbook读取模板,批量填充并导出文件

1、pom文件导入 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.0</version> </dependency> <dependency><groupId>org.apache.poi</groupId><artifactId>…...

Lazada新店运营秘籍自养号测评技术

跨境行业的前途虽然大好&#xff0c;但要想真正从中分一杯羹并非易事。东南亚市场前景大好&#xff0c;而作为其主流在线购物网站之一&#xff0c;Lazada吸引了众多卖家和买家。作为新手来说&#xff0c;注册好Lazada之后&#xff0c;店铺下一步该怎么做呢&#xff1f;赶紧来看…...

python:逐像素处理遥感数据时间序列数据(求时间序列最大值、最大值所对应的索引、最大值所在的时间)

作者:CSDN @ _养乐多_ 本文记录了使用gdal、ras、numpy 库实现遥感时间序列数据逐像素处理的代码。并以求NADVI时间序列最大值为例。代码可扩展到其他多种对时间序列的处理,比如MK趋势分析,求时间序列中值、众数、标准差、和,时间序列拟合、异常检测、机器学习预测等多种应…...

SpringCloudGateway--过滤器(自定义filter)

目录 一、概览 二、通过GatewayFilter实现 三、继承AbstractGatewayFilterFactory 一、概览 当使用Spring Cloud Gateway构建API网关时&#xff0c;可以利用Spring Cloud Gateway提供的内置过滤器&#xff08;filter&#xff09;来实现对请求的处理和响应的处理。过滤器可以…...

【docker】安装 showdoc

1. 下载镜像 2.新建存放showdoc数据的目录 3.启动showdoc容器 4.打开网页 1. 下载镜像 # 原版官方镜像安装命令(中国大陆用户不建议直接使用原版镜像&#xff0c;可以用后面的加速镜像) docker pull star7th/showdoc # 中国大陆镜像安装命令&#xff08;安装后记得执行docke…...

智慧公厕:科技赋予公共卫生新生命,提升城市管理品质

在现代化城市中&#xff0c;公共卫生设施的发展与提升一直是对城市管理者和市民的共同期望。然而&#xff0c;传统的公共厕所常常令人困扰&#xff0c;脏乱臭成为难题。为了解决这一难题&#xff0c;广州中期科技科技有限公司全新升级的智慧公厕整体解决方案&#xff0c;补誉为…...

深度学习_2 数据操作之数据预处理

数据操作 机器学习包括的核心组件有&#xff1a; 可以用来学习的数据&#xff08;data&#xff09;&#xff1b;如何转换数据的模型&#xff08;model&#xff09;&#xff1b;一个目标函数&#xff08;objective function&#xff09;&#xff0c;用来量化模型的有效性&…...

在美团和阿里6年,很难却也真实...

先简单的说下&#xff0c;本人6年工作经验&#xff0c;曾就职于某大型国企&#xff0c;公司研究院成员&#xff0c;也就职过美团担任高级测试开发工程师&#xff0c;有丰富的高并发大型项目经验。 后端高并发、高性能、高可用性开发&#xff0c;自动化测试框架开发以及软件自动…...

2、NLP文本预处理技术:词干提取和词形还原

一、说明 在上一篇文章中&#xff0c;我们解释了文本预处理的重要性&#xff0c;并解释了一些文本预处理技术。在本文中&#xff0c;我们将介绍词干提取和词形还原主题。 词干提取和词形还原是两种文本预处理技术&#xff0c;用于将单词还原为其基本形式或词根形式。这些技术的…...

Fabric官方示例测试网络搭建

目录 一、参考文档二、环境依赖三、Fabric源码安装3.1、创建链目录3.2、下载源码3.3、修改安装脚本3.4、开始安装3.4.1、执行安装脚本3.4.2、手动下载ca和二进制配置包 四、启动测试网络五、使用测试网络5.1、创建应用通道5.2、部署链码5.3、发送交易 六、关闭测试网络 一、参考…...

ubuntu20.04 conda pack 打包虚拟环境,直接将其用到其他终端

在本机ubuntu20.04下配置的虚拟环境&#xff0c;想到将其整个放到新建的docker(ubuntu20.04)下使用&#xff0c;操作步骤如下&#xff1a; # 一、在ubuntu1下打包虚拟环境 # 安装conda-pack pip install conda-pack# 进入需要打包的虚拟环境,这里将目标虚拟环境名称为goal_env…...

云原生-AWS EC2使用、安全性及国内厂商对比

目录 什么是EC2启动一个EC2实例连接一个实例控制台ssh Security groups规则默认安全组与自定义安全组 安全性操作系统安全密钥泄漏部署应用安全元数据造成SSRF漏洞出现时敏感信息泄漏网络设置错误 厂商对比参考 本文通过实操&#xff0c;介绍了EC2的基本使用&#xff0c;并在功…...

【Proteus仿真】【Arduino单片机】简易电子琴

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用无源蜂鸣器、按键等。 主要功能&#xff1a; 系统运行后&#xff0c;按下K1-K7键发出不同音调。 二、软件设计 /* 作者&#xff1a;嗨小易&a…...

QT5.15.2 for Android 真机调试

一、准备就绪 1、一台安卓手机 1&#xff09;手机需要进入开发者选项 2&#xff09;准备一根USB线&#xff0c;需要用usb线连接电脑 2、QT5需要 Android搭建好环境&#xff08;教程可以访问我另一篇文章&#xff09; 二、调试 1、用usb线连接好电脑并进入开发者选项&…...

Mysql my.cnf配置文件参数详解

Linux 操作系统中 MySQL 的配置文件是 my.cnf&#xff0c;一般会放在 /etc/my.cnf 或 /etc/mysql/my.cnf 目录下。 如果你使用 rpm 包安装 MySQL 找不到 my.cnf 文件&#xff0c;可参考如下&#xff1a; 第一步&#xff1a; 通过cd命令 cd /usr/share/mysql 来到这个目录&#…...

搞不定CAN总线匹配电阻?实测告诉你120Ω电阻怎么加、阻值怎么测、位置怎么放才不出错

CAN总线终端电阻实战指南&#xff1a;从原理到排错的完整解决方案 当你的CAN总线通信频繁出现TxError或NO ACK错误时&#xff0c;终端电阻配置往往是第一个需要检查的环节。许多工程师虽然知道"两端各加120Ω电阻"的基本原则&#xff0c;但在实际项目中仍然会犯各种看…...

OpenClaw隐私保护方案:Qwen3.5-9B本地处理医疗图片的10个细节

OpenClaw隐私保护方案&#xff1a;Qwen3.5-9B本地处理医疗图片的10个细节 1. 为什么选择本地化医疗图片处理 去年帮家人整理体检报告时&#xff0c;我遇到一个两难问题&#xff1a;既想用AI分析CT影像的异常阴影&#xff0c;又担心把敏感数据上传到第三方平台。这个矛盾促使我…...

别再折腾了!Windows 10/11 下用 Anaconda 一键搞定 OpenPose Python 环境(附 CUDA 11.8 配置)

告别环境配置噩梦&#xff1a;Anaconda三分钟部署OpenPose全攻略 当你在深夜第三次重装CUDA驱动时&#xff0c;是否怀疑过人生&#xff1f;作为计算机视觉领域的里程碑式工具&#xff0c;OpenPose的人体姿态识别能力令人惊叹&#xff0c;但其复杂的环境配置却让无数开发者折戟沉…...

Go Routine 调度器的核心逻辑

Go语言凭借其轻量级线程——Goroutine&#xff0c;成为高并发编程的热门选择。而Goroutine的高效运行&#xff0c;离不开其底层调度器的精妙设计。本文将深入解析Goroutine调度器的核心逻辑&#xff0c;揭示其如何实现数万并发任务的流畅调度。调度模型&#xff1a;M-P-G三级协…...

Matlab Simulink四分之一主动悬架:PID与模糊PID控制器在车身加速度上的对比研究

项目&#xff1a;Matlab Simulink四分之一主动悬架&#xff0c;针对车身加速度的PID和模糊Pid控制器对比 详情&#xff1a;根据汽车的半主动悬架系统&#xff0c;通过Simulink建立二自由度1/4车辆简化模型以及路面激励模型&#xff0c;以车身垂直加速度为控制对象&#xff0c;悬…...

3D 效果与深度:现代 UI 设计的立体革命

3D 效果与深度&#xff1a;现代 UI 设计的立体革命探索如何在 2024 年通过 CSS 和 Flutter 实现令人惊叹的 3D UI 效果&#xff0c;为用户界面增添深度和层次感。一、3D 设计的崛起 在当今的数字设计领域&#xff0c;平面化设计已经不再是唯一的选择。随着硬件性能的提升和浏览…...

Windows下OpenClaw安装详解:对接Kimi-VL-A3B-Thinking图文模型

Windows下OpenClaw安装详解&#xff1a;对接Kimi-VL-A3B-Thinking图文模型 1. 为什么选择OpenClaw与Kimi-VL-A3B-Thinking组合 去年我在处理大量图文资料归档时&#xff0c;发现手动整理效率极低。直到尝试将OpenClaw与Kimi-VL-A3B-Thinking模型对接后&#xff0c;才真正实现…...

drm_gpusvm 与 drm_pagemap 执行顺序分析

概述 在 SVM&#xff08;Shared Virtual Memory&#xff09;实现中&#xff0c;drm_gpusvm 和 drm_pagemap 分属两个不同的抽象层&#xff0c;协同完成 GPU 对进程虚拟地址空间的共享访问。两者的执行顺序并非固定的"先底层后上层"&#xff0c;而是根据操作场景有不同…...

Linux 的 id 命令

id 是 Linux 系统中一个常用的命令行工具&#xff0c;用于显示用户和组的身份信息。 基本功能 id 命令可以显示当前用户或指定用户的以下信息&#xff1a; 用户 ID (UID)主组 ID (GID)所属的所有组 (Groups)用户名和组名&#xff08;当与数字 ID 对应时&#xff09; 常用命…...

解密Prompt系列69. 从上下文管理到Runtime操作系统

AM&#xff09;”&#xff0c;将 Runtime 视为“状态&#xff08;State&#xff09;”&#xff0c;构建一套属于智能体的“操作系统”。 最近&#xff0c;ByteDance 的 Context-Folding、MIT 的 RLM、以及热门项目 Ralph 的出现&#xff0c;共同指向了一个极其明确的趋势&…...