使用 Clojure 进行 OpenCV 开发简介

从 OpenCV 2.4.4 开始,OpenCV 支持使用与 Android 开发几乎相同的接口进行桌面 Java 开发。

Clojure 是由 Java 虚拟机托管的一种现代 LISP 方言,它提供了与底层 JVM 的完全互操作性。这意味着我们甚至应该能够使用 Clojure REPL(Read Eval Print Loop)作为底层 OpenCV 引擎的交互式可编程接口。

我们将在本教程中执行的操作

本教程将帮助您设置一个基本的 Clojure 环境,以便在完全可编程的 CLojure REPL 中以交互方式学习 OpenCV。

教程源代码

您可以在 OpenCV 存储库的文件夹中找到该示例的可运行源代码。按照教程中的说明安装 OpenCV 和 Clojure 后,发出以下命令以从命令行运行示例。samples/java/clojure/simple-sample

cd 路径/to/samples/java/clojure/simple-sample
莱恩润

序言

有关安装具有桌面 Java 支持的 OpenCV 的详细说明,请参阅相应的教程”。

如果您赶时间,以下是在 Mac OS X 上安装 OpenCV 的最低快速入门指南:

注意

我假设您已经安装了 xcode、jdk 和 Cmake。

cd ~/
mkdir 选项
git clone https://github.com/opencv/opencv.git
光盘opencv
git checkout 2.4
mkdir 构建
CD 构建
cmake -DBUILD_SHARED_LIBS=关闭 ..
...
...
制造 -j8
# 可选
# make install

安装 Leiningen

一旦你安装了支持桌面java的OpenCV,唯一的其他要求就是安装Leiningeng,它允许你管理CLJ项目的整个生命周期。

可用的安装指南非常容易遵循:

  1. 下载脚本
  2. 把它放在你的$PATH上(如果它在你的路径上,cf./bin 是一个不错的选择。
  3. 将脚本设置为可执行。(即 chmod 755/bin/lein)。

如果您在 Windows 上工作,请按照以下说明操作

现在,您已经拥有了 OpenCV 库和完全安装的基本 Clojure 环境。现在需要的是配置 Clojure 环境以与 OpenCV 库进行交互。

安装 localrepo Leiningen 插件

Leiningen 原生支持的命令集(用 Leiningen 术语来说就是任务)可以很容易地通过各种插件进行扩展。其中之一是 lein-localrepo 插件,它允许将任何 jar lib 作为工件安装在机器的本地 maven 存储库中(通常在用户名的 /.m2/repository 目录中)。

我们将使用这个 lein 插件将 Java 和 Clojure 使用 opencv 库所需的 opencv 组件添加到本地 maven 存储库中。

一般来说,如果你只想在项目基础上使用一个插件,可以直接添加到lein创建的CLJ项目中。

相反,当您希望插件可用于用户名空间中的任何 CLJ 项目时,您可以将其添加到 /.lein/ 目录中的 profiles.clj。

lein-localrepo 插件在其他 CLJ 项目中对我有用,在这些项目中,我需要调用由 Java 接口包装的本机库。因此,我决定将其提供给任何 CLJ 项目:

mkdir ~/.lein

在 /.lein 目录中创建名为 profiles.clj 的文件,并将以下内容复制到其中:

{:user {:p lugins [[lein-localrepo “0.5.2”]]}}

在这里,我们说 lein-localrepo 插件的版本“0.5.2”将可用于 lein 创建的任何 CLJ 项目的 :user 配置文件。

您无需执行任何其他操作即可安装该插件,因为当您第一次发出任何 lein 任务时,它将自动从远程存储库下载。

将特定于 java 的库安装为本地存储库

如果您遵循了在计算机上安装 OpenCV 的标准文档,您应该在构建 OpenCV 的目录下找到以下两个库:

  • build/bin/opencv-247.jar java 库
  • build/lib/libopencv_java247.dylib 原生库(或 .so 在你构建的 OpenCV 一个 GNU/Linux 操作系统中)

它们是 JVM 与 OpenCV 交互所需的唯一 opencv 库。

拆解所需的 opencv 库

创建一个新目录以存储在上述两个库中。首先将 opencv-247.jar 库复制到其中。

cd ~/选择
mkdir clj-opencv
光盘 CLJ-openCV
cp ~/opt/opencv/build/bin/opencv-247.jar .

第一个库完成。

现在,为了能够将 libopencv_java247.dylib 共享的原生库添加到本地 maven 存储库中,我们首先需要将其打包为 jar 文件。

必须将本机库复制到模仿操作系统和体系结构名称的目录布局中。我正在使用具有 X86 64 位架构的 Mac OS X。所以我的布局如下:

mkdir -p 本机/macosx/x86_64

将 libopencv_java247.dylib 库复制到 x86_64 目录中。

cp ~/opt/opencv/build/lib/libopencv_java247.dylib 本机/macosx/x86_64/

如果您从不同的操作系统/体系结构对运行 OpenCV,以下是您可以选择的映射摘要。

操作系统
Mac OS X - > macosx
Windows -> Windows
Linux -> linux
SunOS -> solaris
架构
amd64 -> x86_64
x86_64 -> x86_64
x86 -> x86
i386 -> x86
胳膊 -> 胳膊
sparc -> sparc

将本机 lib 打包为 jar

接下来,您需要使用 jar 命令从目录创建新的 jar 文件,将本机 lib 打包到 jar 文件中。

jar -cMf opencv-native-247.jar 原生

请注意,ehe M 选项指示 jar 命令不为工件创建 MANIFEST 文件。

目录布局应如下所示:

.
|__ 原生
| |__ macOSX
| |__ x86_64
| |__ libopencv_java247.dylib
|
|__ opencv-247.jar
|__ opencv-native-247.jar
3 个目录,3 个文件

本地安装 jar

现在,我们已准备好借助 lein-localrepo 插件将这两个 jar 作为工件添加到本地 maven 存储库中。

lein localrepo 安装 opencv-247.jar opencv/opencv 2.4.7

在这里,localrepo 安装任务创建了 2.4.7。从 opencv-247.jar 库发布 OpenCV/OpenCV Maven 工件,然后将其安装到本地 Maven 存储库中。然后,opencv/opencv 工件将可用于任何符合 maven 的项目(Leiningen 内部基于 maven)。

对之前包装在新 jar 文件中的本机库执行相同的操作。

lein localrepo 安装 opencv-native-247.jar opencv/opencv-native 2.4.7

请注意,这两个工件的 groupId opencv 是相同的。现在,我们已准备好创建一个新的 CLJ 项目来开始与 OpenCV 进行交互。

创建项目

使用终端中的 lein new 任务创建新的 CLJ 项目。

# cd (例如 ~/devel)
Lein 新简单示例
基于“默认”模板生成一个名为 simple-sample 的项目。
要查看其他模板(应用程序、lein 插件等),请尝试“lein help new”。

上述任务将创建以下简单示例目录布局:

树简单示例/
简单样品/
|__ 许可证
|__ README.md
|__ 文档
| |__ intro.md
|
|__ project.clj
|__ 资源
|__ 来源
| |__ simple_sample
| |__ core.clj
|__ 测试
|__ simple_sample
|__ core_test.clj
6 个目录,6 个文件

我们需要添加两个 opencv 工件作为新创建项目的依赖项。打开 project.clj 并修改其 dependencies 部分,如下所示:

(defproject simple-sample “0.1.0-SNAPSHOT”
description “FIXME: write description”
url “http://example.com/FIXME”
license {:name “Eclipse 公共许可证”
url “http://www.eclipse.org/legal/epl-v10.html”}
依赖项 [[org.clojure/clojure “1.5.1”]
[opencv/opencv “2.4.7”] ;添加行
[opencv/opencv-本机 “2.4.7”]]);添加行

请注意,Clojure 编程语言也是一个 jar 工件。这就是 Clojure 被称为托管语言的原因。

要验证一切是否正常,请发出 lein deps 任务。第一次运行 lein 任务时,在执行任务本身之前,需要一些时间来下载所有必需的依赖项。

CD 简单样本
莱恩·德普斯
...

deps 任务从 project.clj 和 /.lein/profiles.clj 文件中读取和合并 simple-sample 项目的所有依赖项,并验证它们是否已缓存在本地 maven 存储库中。如果任务返回时没有关于无法检索两个新工件的消息,则您的安装是正确的,否则请返回并仔细检查您是否正确执行了所有操作。

使用 OpenCV 进行 REPLING

现在 cd 在 simple-sample 目录中并发出以下 lein 任务:

CD 简单样本

莱恩·雷普尔

..

nREPL 服务器在主机 127.0.0.1 上的端口 50907 上启动

REPL-y 0.3.0 版本

Clojure 1.5.1 版本

文档:(doc function-name-here)

(find-doc “部分名称在这里”)

源:(source function-name-here)

Javadoc:(javadoc java-object-or-class-here)

退出:Ctrl+D 或(退出)或(退出)

结果:存储在变量 *1、*2、*3 中,异常存储在 *e 中

用户=>

您可以通过发出任何要计算的 CLJ 表达式来立即与 REPL 进行交互。

用户=> (+ 41 1)

42

user=> (println “你好,OpenCV!”)

你好,OpenCV!

user=> (defn foo [] (str “bar”))

#'用户/foo

用户=> (foo)

“酒吧”

当从基于 lein 的项目的主目录运行时,即使 lein repl 任务自动加载所有项目依赖项,您仍然需要加载 opencv 本机库才能与 OpenCV 交互。

user=> (clojure.lang.RT/loadLibrary org.opencv.core.Core/NATIVE_LIBRARY_NAME)

然后,您可以通过引用其类的完全限定名称来开始与 OpenCV 交互。

注意

在这里,您可以找到完整的 OpenCV Java API。

user=> (org.opencv.core.Point. 0 0)

#<点 {0.0, 0.0}>

在这里,我们创建了一个二维的 opencv Point 实例。即使 OpenCV 的 java 接口中包含的所有 java 包都可以立即从 CLJ REPL 获得,在 Point 前面加上前缀也是非常烦人的。具有完全限定包名称的实例构造函数。

幸运的是,CLJ 提供了一种非常简单的方法,通过直接导入 Point 类来克服这种烦恼。

user=> (import 'org.opencv.core.Point)

org.opencv.core.Point(组织.opencv.core.Point)

user=> (def p1 (点 0 0))

#'用户/p1

用户=> p1

#<点 {0.0, 0.0}>

user=> (def p2 (点 100 100))

#'用户/p2

我们甚至可以检查实例的类,并验证符号的值是否是 Point java 类的实例。

user=>(类 P1)

org.opencv.core.Point(组织.opencv.core.Point)

user=> (instance? org.opencv.core.Point p1)

如果我们现在想使用 opencv Rect 类来创建一个矩形,我们再次必须完全限定它的构造函数,即使它留在 Point 类的同一个 org.opencv.core 包中。

user=> (org.opencv.core.Rect. p1, p2)

#<矩形 {0, 0, 100x100}>

同样,CLJ 导入工具非常方便,可让您一次映射更多符号。

user=> (import '[org.opencv.core 点矩形大小])

org.opencv.core.Size

user=> (def r1 (Rect. p1 p2))

#'用户/r1

用户=> r1

#<矩形 {0, 0, 100x100}>

user=>(类 R1)

org.opencv.core.Rect

user=> (instance? org.opencv.core.Rect r1)

user=>(大小:100、100)

#<尺寸 100x100>

user=> (def sq-100 (大小 100 100))

#'用户/sq-100

user=>(SQ-100 类)

org.opencv.core.Size

user=> (instance? org.opencv.core.Size sq-100)

显然,您也可以在实例上调用方法。

用户=> (.area r1)

10000.0

用户=> (.area sq-100)

10000.0

或者修改成员字段的值。

user=> (set!(.x p1) 10)

10

用户=> p1

#<点 {10.0, 0.0}>

user=> (set!(.宽度 sq-100) 10)

10

user=> (set!(.高度 sq-100) 10)

10

用户=> (.area sq-100)

100.0

如果您发现自己不记得 OpenCV 类的行为,REPL 让您有机会轻松搜索相应的 javadoc 文档:

user=> (javadoc 矩形)

“http://www.google.com/search?btnI=I%27m%20Feeling%20Lucky&q=allinurl:org/opencv/core/Rect.html”

在 REPL 中模拟 OpenCV Java 教程示例

现在让我们尝试将 OpenCV Java 教程示例移植到 Clojure。我们将在 REPL 上对其进行评估,而不是将其写入源文件中。

以下是引用示例的原始 Java 源代码。

导入 org.opencv.core.Mat;
导入 org.opencv.core.CvType;
导入 org.opencv.core.Scalar;
简单示例 {
static{ System.loadLibrary(“opencv_java244”); }
公共静态无效main(String[] args) {
垫子 m = 新垫子(5, 10, CvType.CV_8UC1, 标量(0));
System.out.println(“OpenCV 垫子:” + m);
垫子 mr1 = m.row(1);
mr1.setTo(标量(1));
垫子 mc5 = m.col(5);
mc5.setTo(标量(5));
System.out.println(“OpenCV 垫数据:\n” + m.dump());
}
}

向项目添加注入

在开始编码之前,我们希望消除在启动新的 REPL 以交互方式加载原生 opencv 库时与之交互的无聊需求。

首先,通过在 REPL 提示符下计算 (exit) 表达式来停止 REPL。

user=>(退出)
再见!

然后打开 project.clj 文件并按如下方式进行编辑:

(defproject simple-sample “0.1.0-SNAPSHOT”
...
注入 [(clojure.lang.RT/loadLibrary org.opencv.core.Core/NATIVE_LIBRARY_NAME)])

在这里,我们说在运行 REPL 时加载 opencv 本机库,这样我们就不必再记住手动执行。

重新运行 lein repl 任务

莱恩·雷普尔
nREPL 服务器在主机 127.0.0.1 上的端口 51645 上启动
REPL-y 0.3.0 版本
Clojure 1.5.1 版本
文档:(doc function-name-here)
(find-doc “部分名称在这里”)
源:(source function-name-here)
Javadoc:(javadoc java-object-or-class-here)
退出:Ctrl+D 或(退出)或(退出)
结果:存储在变量 *1、*2、*3 中,异常存储在 *e 中
用户=>

导入感兴趣的 OpenCV java 接口。

user=> (import '[org.opencv.core Mat CvType 标量])
org.opencv.core.标量

我们将几乎逐字逐句地模仿原始的 OpenCV java 教程:

  • 创建一个 5x10 矩阵,其所有元素都初始化为 0
  • 将第二行的每个元素的值更改为 1
  • 将第 6 列的每个元素的值更改为 5
  • 打印得到的矩阵的内容
user=> (def m (Mat. 5 10 CvType/CV_8UC1 (Scalar. 0 0)))
#'用户/m
用户=> (def mr1 (.row m 1))
#'用户/mr1
user=> (.setTo mr1 (标量 1 0))
#<垫垫 [ 1*10*CV_8UC1, isCont=true, isSubmat=true, nativeObj=0x7fc9dac49880, dataAddr=0x7fc9d9c98d5a ]>
用户=> (def mc5 (.col m 5))
#'用户/mc5
user=> (.setTo mc5 (标量 5 0))
#<Mat Mat [ 5*1*CV_8UC1, isCont=false, isSubmat=true, nativeObj=0x7fc9d9c995a0, dataAddr=0x7fc9d9c98d55 ]>
用户=> (println (.dump m))
[0, 0, 0, 0, 0, 5, 0, 0, 0, 0;
1, 1, 1, 1, 1, 5, 1, 1, 1, 1;
0, 0, 0, 0, 0, 5, 0, 0, 0, 0;
0, 0, 0, 0, 0, 5, 0, 0, 0, 0;
0, 0, 0, 0, 0, 5, 0, 0, 0, 0]

如果你习惯了一种功能语言,那么所有那些被滥用和变异的名词都会激怒你对动词的偏好。即使 CLJ 互操作语法非常方便和完整,任何 OOP 语言和任何 FP 语言(即 Scala 是一种混合范式编程语言)之间仍然存在阻抗不匹配。

要退出 REPL,请在 REPL 提示符下键入 (exit)、ctr-D 或 (quit)。

user=>(退出)
再见!

以交互方式加载和模糊图像

在下一个示例中,您将学习如何使用以下 OpenCV 方法以交互方式从 REPL 加载、模糊和图像:

  • Highgui 类中的 imread 静态方法,用于从文件中读取图像
  • Highgui 类中的 imwrite 静态方法,用于将图像写入文件
  • Imgproc 类中的 GaussianBlur 静态方法,用于模糊原始图像

我们还将使用 Mat 类,该类从 imread 方法返回并被接受为 GaussianBlur 和 imwrite 方法的主要参数。

将图像添加到项目

首先,我们要将一个镜像文件添加到新创建的目录中,用于存储项目的静态资源。

lena.png

mkdir -p 资源/图像
cp ~/opt/opencv/doc/tutorials/introduction/desktop_java/images/lena.png resource/images/

阅读图片

现在像往常一样启动 REPL,然后从导入我们将要使用的所有 OpenCV 类开始:

莱恩·雷普尔
nREPL 服务器在主机 127.0.0.1 上的端口 50624 上启动
REPL-y 0.3.0 版本
Clojure 1.5.1 版本
文档:(doc function-name-here)
(find-doc “部分名称在这里”)
源:(source function-name-here)
Javadoc:(javadoc java-object-or-class-here)
退出:Ctrl+D 或(退出)或(退出)
结果:存储在变量 *1、*2、*3 中,异常存储在 *e 中
user=> (import '[org.opencv.core Mat Size CvType]
'[org.opencv.imgcodecs imgcodecs]
'[org.opencv.imgproc imgproc])
org.opencv.imgproc.Imgproc

现在从 resources/images/lena.png 文件中读取图像。

user=> (def lena (Highgui/imread “resources/images/lena.png”))
#'用户/莉娜
用户=> Lena
#<垫垫 [ 512*512*CV_8UC3, isCont=true, isSubmat=false, nativeObj=0x7f9ab3054c40, dataAddr=0x19fea9010 ]>

如您所见,通过简单地计算 lena 符号,我们知道 lena.png 是一个 512x512 的 CV_8UC3 元素类型的矩阵。让我们创建一个具有相同尺寸和元素类型的新 Mat 实例。

user=> (def blurred (Mat. 512, 512 CvType/CV_8UC3))
#'用户/模糊
用户=>

现在应用 GaussianBlur 过滤器,使用 lena 作为源矩阵,blurred 作为目标矩阵。

user=> (Imgproc/GaussianBlur lena blurred (Size. 5, 5), 3, 3)

最后一步,只需将模糊的矩阵保存在新的图像文件中即可。

user=> (Highgui/imwrite “resources/images/blurred.png” blured)
user=>(退出)
再见!

以下是莉娜的新模糊图像。

模糊.png

后续步骤

本教程仅介绍在 CLJ REPL 中设置的非常基本的环境,以便能够与 OpenCV 进行交互。

我建议任何 Clojure 新手阅读 Clojure Java Interop 一章,以获得与任何未包装在 Clojure 中的纯 Java 库进行互操作所需的所有知识,以使其在 Clojure 中以更惯用和功能化的方式使用。

OpenCV Java API 不会根据 Qt 封装 highgui 模块功能(例如 namedWindow 和 imshow.如果您想创建窗口并在从 REPL 与 OpenCV 交互时将图像显示在其中,那么目前您只能自己动手。你可以使用 Java Swing 来填补这个空白。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录 Leetcode1. 两数之和

题目&#xff1a; 代码&#xff08;首刷看解析 2024年1月15日&#xff09;&#xff1a; class Solution { public:vector<int> twoSum(vector<int>& nums, int target) {int another 0;unordered_map<int,int> hash;for(int i 0; i < nums.size();…

arcgis javascript api4.x以basetilelayer方式加载天地图web墨卡托(wkid:3857)坐标系

需求&#xff1a; arcgis javascript api4.x以basetilelayer方式加载天地图web墨卡托&#xff08;wkid&#xff1a;3857&#xff09;坐标系 效果图&#xff1a; 代码&#xff1a; 提示&#xff1a; 2个文件放同一个文件夹下 MyCustomTileLayer.js define([exports, "…

Grind75第10天 | 133.克隆图、994.腐烂的橘子、79.单词搜索

133.克隆图 题目链接&#xff1a;https://leetcode.com/problems/clone-graph 解法&#xff1a; 这个题是对无向图的遍历&#xff0c;可以用深度优先搜索和广度有限搜索。 下面这个图比较清楚的说明了两种方法的区别。 DFS&#xff1a;从A开始克隆&#xff0c;遍历两个邻居…

IntelliJ IDEA - 快速去除 mapper.xml 告警线和背景(三步走)

1、去掉 No data sources configure 警告 Settings&#xff08;Ctrl Alt S&#xff09; ⇒ Editor ⇒ Inspections ⇒ SQL ⇒ No data sources configure 2、去掉 SQL dialect is not configured 警告 Settings&#xff08;Ctrl Alt S&#xff09; ⇒ Editor ⇒ Inspecti…

C语言经典算法之冒泡排序算法

目录 前言 建议&#xff1a; 简介&#xff1a; 一、代码实现 二、时空复杂度 时间复杂度&#xff1a; 空间复杂度&#xff1a; 总结&#xff1a; 前言 建议&#xff1a; 1.学习算法最重要的是理解算法的每一步&#xff0c;而不是记住算法。 2.建议读者学习算法的时候…

决策树(公式推导+举例应用)

文章目录 引言决策树学习基本思路划分选择信息熵信息增益增益率&#xff08;C4.5&#xff09;基尼指数&#xff08;CART&#xff09; 剪枝处理预剪枝&#xff08;逐步构建决策树&#xff09;后剪枝&#xff08;先构建决策树再剪枝&#xff09; 连续值与缺失值处理连续值处理缺失…

rsync远程同步服务

一、rsync&#xff08;远程同步&#xff09; rsync&#xff08;Remote Sync&#xff0c;远程同步&#xff09; 是一个开源的快速备份工具&#xff0c;可以在不同主机之间镜像同步整个目录树&#xff0c;支持增量备份&#xff0c;并保持链接和权限&#xff0c;且采用优化的同步…

初识物联网

1&#xff1a;什么是IOT&#xff1a; 物联网的英文名称是Internet of Things。IoT则是Internet of Things的缩写。因此, 物联网 IoT。 通俗地说&#xff0c;物联网是互联网的一种拓展。我们知道互联网是由无数的计算机和智能手机交错连接而编织成的一张网。而正是有了像NodeM…

大模型LLM Agent在 Text2SQL 应用上的实践

1.前言 在上篇文章中「如何通过Prompt优化Text2SQL的效果」介绍了基于Prompt Engineering来优化Text2SQL效果的实践&#xff0c;除此之外我们还可以使用Agent来优化大模型应用的效果。 本文将从以下4个方面探讨通过AI Agent来优化LLM的Text2SQL转换效果。 1 Agent概述2 Lang…

基于Python编程实现简单网络爬虫实现

引言 网络爬虫&#xff08;英语&#xff1a;web crawler&#xff09;&#xff0c;也叫网络蜘蛛&#xff08;spider&#xff09;&#xff0c;是一种用来自动浏览万维网的网络机器人。其目的一般为编纂网络索引。 --维基百科 网络爬虫可以将自己所访问的页面保存下来&#xff0c…

ByConity 社区回顾|ByConity 和开发者们一起展望未来,携手共进!

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 新年伊始&#xff0c;我们想在这里感谢一群 ByConity 社区的小伙伴们。 正是因为有社区的开发者的支持&#xff0c;截止到 2023 年底&#xff0c;ByConity GitHub …

电脑的任务栏怎么恢复到底下?简单的4个方法帮你解决!

“我在使用电脑的时候突然发现电脑底部的任务栏不见了&#xff0c;有什么方法可以将任务栏恢复到底下吗&#xff1f;快给我出出主意吧&#xff01;” 在使用电脑时&#xff0c;我们可能会发现电脑的任务栏跑到屏幕顶部或消失的情况。这不仅影响了我们的使用体验&#xff0c;还可…

SMD NTC Thermistor NTC热敏电阻产品基本参数定义

热敏电阻器&#xff08;Thermistor&#xff09;是一种电阻值对温度极为灵敏的半导体元件&#xff0c;温度系数可分为Positive Temperature Coefficient 正温度系数热敏电阻又称PTC热敏电阻和Negative Temperature Coefficient 负温度系数热敏电阻又称NTC热敏电阻. NTC热敏电…

20240115-【UNITY 学习】第一人称移动增加斜坡移动、冲刺和蹲伏功能

直接修改或者替换PlayerMovement_01.cs using System.Collections; using System.Collections.Generic; using UnityEngine;public class PlayerMovement_02 : MonoBehaviour {private float moveSpeed; // 玩家移动速度public float walkSpeed 7; // 行走速度public float sp…

运筹说 第91期 | 网络计划经典例题讲解

通过前几期的学习&#xff0c;我们已经学会了网络图的基本概念、时间参数的计算&#xff0c;并且掌握了随机网络的概念、图解评审法的基本原理和基本解法&#xff0c;本期小编带大家学习网络计划在经济管理中的应用。 在实际工作中&#xff0c;我们能发现网络计划在经济管理中…

ThingsPanel部署和使用

前置条件&#xff1a; 首先默认大家有一台服务器或者云服务器并且已经搭建好环境。小编是基于Linux宝塔环境以Docker安装ThingsPanel平台。 一.Docker和Docker-compose 1.概述 Docker是一个开源的容器化平台&#xff0c;它可以帮助开发者将应用程序与其依赖项打包到一个轻量…

Windows10 Docker Desktop安装

一、简介 Docker Desktop是Docker公司推出的一款桌面应用程序&#xff0c;它提供了一个用户友好的界面&#xff0c;方便开发人员在本地环境中使用容器技术。 容器是一种轻量级的虚拟化技术&#xff0c;可以将应用程序和其依赖项打包在一起&#xff0c;形成一个独立、可移植的…

gateway Redisson接口级别限流解决方案

文章目录 前言1. 计数器算法&#xff08;固定窗口限流器&#xff09;2. 滑动窗口日志限流器3. 漏桶算法&#xff08;Leaky Bucket&#xff09;4. 令牌桶算法&#xff08;Token Bucket&#xff09;5. 限流队列应用场景实现工具 一、Redisson简介二、Redisson限流器的原理三、Red…

Docker实战06|深入剖析Docker Run命令

前几篇文章中&#xff0c;重点讲解了Linux Namespace、Cgroups、AUFS的核心原理&#xff0c;同样也是Docker的底层原理实现。目录如下&#xff1a; • 《Docker实战01&#xff5c;容器与开发语言》 • 《Docker实战02&#xff5c;Namespace》 • 《Docker实战03&#xff5c;C…

RPA与通知机器人的完美结合

写在前面 在现代快节奏的工作环境中&#xff0c;我们经常会面临多个任务同时进行的情况&#xff0c;你还在为时间不够用、忙碌而惆怅吗&#xff1f;你还在为时刻盯着电脑流程而烦恼吗&#xff1f;你还在为及时收不到自己的自动化任务进度而焦躁吗&#xff1f;别担心&#xff0…