OpenCV 图形API(4)内核 API
- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
G-API 背后的核心理念是可移植性——使用 G-API 构建的流水线必须是可移植的(或者至少具备可移植的能力)。这意味着,当为新平台编译时,它要么可以直接运行,要么 G-API 提供必要的工具以确保其在该平台上运行,而算法本身几乎不需要修改。
这一理念通过将内核接口与其具体实现分离来实现。一旦使用内核接口构建了流水线,它就变得与实现无关——实现细节(即使用哪些内核)是在单独的阶段(图编译)中传递的。
内核-实现层次结构可能如下所示:
流水线表达与内核定义
一个流水线本身只能用诸如A、B等术语来表达,而选择使用哪种实现则成为一个外部参数。
定义一个内核
G-API 提供了一个宏 G_TYPED_KERNEL() 来定义一个新的内核接口:
#include <opencv2/gapi.hpp>
G_TYPED_KERNEL(GFilter2D,<cv::GMat(cv::GMat,int,cv::Mat,cv::Point,double,int,cv::Scalar)>,"org.opencv.imgproc.filters.filter2D")
{static cv::GMatDesc // outMeta's return value typeoutMeta(cv::GMatDesc in , // descriptor of input GMatint ddepth , // depth parametercv::Mat /* coeffs */, // (unused)cv::Point /* anchor */, // (unused)double /* scale */, // (unused)int /* border */, // (unused)cv::Scalar /* bvalue */ ) // (unused){return in.withDepth(ddepth);}
};
这个宏是定义新类型的一个快捷方式。它需要三个参数来注册一个新的类型,并且要求类型体必须存在(见下文)。宏的参数包括:
- 内核接口名称 – 同时作为使用此宏定义的新类型的名称;
- 内核签名 – 类似于 std::function<> 的签名,用于定义内核的API;
- 内核的唯一名称 – 当系统中内核的类型信息被移除时用于识别内核。
内核声明可以看作函数声明——在这两种情况下,新实体都必须根据其定义的方式来使用。
内核签名定义了内核的使用语法——即在图构建期间它接受哪些参数。实现也可以使用这个签名将其转换为特定后端的回调签名(参见下一章)。
内核可以接受任何类型的值,而G-API动态类型(如cv::GMat)有特殊的处理方式。所有其他类型对G-API来说是不透明的,在outMeta()或执行回调中按原样传递。
内核的返回值 只能是G-API动态类型——即cv::GMat、cv::GScalar或cv::GArray。如果一个操作有多个输出,应该将其包装在一个std::tuple<>中(该元组只能包含上述提到的G-API类型)。不支持任意数量的输出操作。
一旦定义了一个内核,就可以在流水线中使用由G-API提供的特殊方法"::on()"。这种方法具有与内核定义相同的签名,因此这段代码:
cv::GMat in;
cv::GMat out = GFilter2D::on(/* GMat */ in,/* int */ -1,/* Mat */ conv_kernel_mat,/* Point */ cv::Point(-1,-1),/* double */ 0.,/* int */ cv::BORDER_DEFAULT,/* Scalar */ cv::Scalar(0));
是一个完全合法的构造方式。然而,这个例子有些冗长,因此通常内核声明会附带一个C++函数包装器(“工厂方法”),以启用可选参数、更紧凑的语法、Doxygen注释等:
cv::GMat filter2D(cv::GMat in,int ddepth,cv::Mat k,cv::Point anchor = cv::Point(-1,-1),double scale = 0.,int border = cv::BORDER_DEFAULT,cv::Scalar bval = cv::Scalar(0))
{return GFilter2D::on(in, ddepth, k, anchor, scale, border, bval);
}
因此,现在它可以像这样使用:
cv::GMat in;
cv::GMat out = filter2D(in, -1, conv_kernel_mat);
额外信息
在当前版本中,内核声明体(大括号内的所有内容)必须包含一个静态函数 outMeta()。此函数建立了操作输入和输出元数据之间的功能依赖关系。
元数据是关于内核操作的数据的信息。由于非G-API类型对G-API来说是不透明的,G-API只关心G* 数据描述符(例如cv::GMat的尺寸和格式等)。
outMeta()也是如何将内核签名转换为派生回调的一个例子——请注意,在这个例子中,outMeta()的签名严格遵循内核签名(在宏中定义),但有所不同——内核期望的是cv::GMat,而outMeta()接收并返回的是cv::GMatDesc(这是G-API结构体,用于cv::GMat的元数据)。
outMeta()的目的在于从输入到输出传播元数据信息,并推断内部(中间、临时)数据对象的元数据。这些信息对于进一步的流水线优化、内存分配以及G-API框架在图编译期间执行的其他操作是必需的。
实现一个内核
一旦内核被声明,其接口可以用于在不同的后端实现该内核的版本。这一概念自然地映射自面向对象编程中的“接口/实现”模式:一个接口可以被多次实现,并且内核的不同实现应该能够相互替换而不破坏算法(流水线)逻辑(里氏替换原则)。
每个后端定义了自己实现内核接口的方式。尽管如此,无论插件是什么,它的内核实现必须从内核接口类型“派生”。
然后,内核实现被组织成内核包。内核包作为编译参数传递给 cv::GComputation::compile(),并提供一些关于如何选择适当的内核的提示给G-API(更多内容见“异构性”[TBD])。
例如,前述的Filter2D在“参考”CPU(OpenCV)插件中这样实现(注意——这是一个简化形式,不正确的边界处理):
#include <opencv2/gapi/cpu/gcpukernel.hpp> // GAPI_OCV_KERNEL()
#include <opencv2/imgproc.hpp> // cv::filter2D()
GAPI_OCV_KERNEL(GCPUFilter2D, GFilter2D)
{static voidrun(const cv::Mat &in, // in - derived from GMatconst int ddepth, // opaque (passed as-is)const cv::Mat &k, // opaque (passed as-is)const cv::Point &anchor, // opaque (passed as-is)const double delta, // opaque (passed as-is)const int border, // opaque (passed as-is)const cv::Scalar &, // opaque (passed as-is)cv::Mat &out) // out - derived from GMat (retval){cv::filter2D(in, out, ddepth, k, anchor, delta, border);}
};
注意CPU(OpenCV)插件是如何转换原始内核签名的:
- 输入 cv::GMat 被替换为 cv::Mat,后者持有底层OpenCV函数调用的实际输入数据;
- 输出 cv::GMat 被转换为额外的输出参数,因此 GCPUFilter2D::run() 比原始内核签名多接受一个参数。
这里对内核开发者的基本直觉是不要关心 cv::Mat 对象是从哪里来的,而不是原来的 cv::GMat——只需遵循插件定义的签名约定。G-API将在执行期间调用此方法,并提供所有必要的信息(并将原始的不透明数据按原样转发)。
复合内核
有时,内核在API层面上是一个单一的事物。这对用户来说很方便,但在特定的实现层面,可能最好有多个内核(子图)来完成这个任务。一个例子是goodFeaturesToTrack()——虽然在OpenCV后端中它可以保持为一个单一的内核,但在Fluid中它变成了复合的——Fluid可以处理Harris响应计算,但不能执行稀疏非极大值抑制和点提取到STL向量:
复合内核的实现可以使用通用宏GAPI_COMPOUND_KERNEL()来定义:
#include <opencv2/gapi/gcompoundkernel.hpp> // GAPI_COMPOUND_KERNEL()
using PointArray2f = cv::GArray<cv::Point2f>;
G_TYPED_KERNEL(HarrisCorners,<PointArray2f(cv::GMat,int,double,double,int,double)>,"org.opencv.imgproc.harris_corner")
{static cv::GArrayDesc outMeta(const cv::GMatDesc &,int,double,double,int,double){// No special metadata for arrays in G-API (yet)return cv::empty_array_desc();}
};
// Define Fluid-backend-local kernels which form GoodFeatures
G_TYPED_KERNEL(HarrisResponse,<cv::GMat(cv::GMat,double,int,double)>,"org.opencv.fluid.harris_response")
{static cv::GMatDesc outMeta(const cv::GMatDesc &in,double,int,double){return in.withType(CV_32F, 1);}
};
G_TYPED_KERNEL(ArrayNMS,<PointArray2f(cv::GMat,int,double)>,"org.opencv.cpu.nms_array")
{static cv::GArrayDesc outMeta(const cv::GMatDesc &,int,double){return cv::empty_array_desc();}
};
GAPI_COMPOUND_KERNEL(GFluidHarrisCorners, HarrisCorners)
{static PointArray2fexpand(cv::GMat in,int maxCorners,double quality,double minDist,int blockSize,double k){cv::GMat response = HarrisResponse::on(in, quality, blockSize, k);return ArrayNMS::on(response, maxCorners, minDist);}
};
// Then implement HarrisResponse as Fluid kernel and NMSresponse
// as a generic (OpenCV) kernel
重要的是要区分复合内核与G-API的高阶函数,即一个看起来像内核但实际上生成子图的C++函数。核心区别在于,复合内核是实现细节,内核实现可以是复合的,也可以不是(取决于后端的能力),而高阶函数在G-API中相当于一种“宏”,因此不能充当一个需要由后端实现的接口。
相关文章:
OpenCV 图形API(4)内核 API
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 G-API 背后的核心理念是可移植性——使用 G-API 构建的流水线必须是可移植的(或者至少具备可移植的能力)。这意味着&…...
pom.xml与.yml,java配置参数传递
pom.xml与 .yml java配置参数传递 在Java项目中,通过 pom.xml 和 .yml 文件(如 application.yml)传递变量通常涉及 构建时(Maven)和 运行时(Spring Boot)两个阶段的配置。以下是具体的实现方法&…...
LeetCode算法题(Go语言实现)_21
题目 给你一个整数数组 arr,如果每个数的出现次数都是独一无二的,就返回 true;否则返回 false。 一、代码实现 func uniqueOccurrences(arr []int) bool {freq : make(map[int]int)// 统计每个数字的出现次数for _, num : range arr {freq[n…...
Docker部署前后端分离项目
镜像下载 在有网络的电脑下载镜像(Windows):依次在CMD命令台执行以下代码 docker pull node:20docker pull openjdk:22-jdkdocker pull mysql:8.0docker pull nginx:1.27 删除镜像代码: docker rmi node:latest 查看镜像列表…...
Linux系统安装MySQL 8.0完整指南(新手友好版)
MySQL作为最流行的开源关系型数据库之一,广泛应用于各种开发和生产环境。本教程将详细介绍在Linux系统上安装MySQL 8.0的全过程,包括卸载旧版本、安装新版本、基础配置和远程连接设置,特别适合Linux新手学习使用。 一、卸载旧版MySQL&#x…...
第二次作业
#创建表,把id设为主键 mysql> create table test02(-> id int primary key, #----主键约束-> name varchar(50)-> ); Query OK, 0 rows affected (0.02 sec) #插入数据测试 mysql> insert into test02 values(1,"成都"); Query OK, 1 r…...
AI大模型下传统 Spring Java工程开发的演进和变化方向
1. 背景和动因 传统Spring开发优势:Spring生态以稳定、模块化、依赖注入(DI)等特性著称,长期支撑企业级应用开发,具备高扩展性和可维护性。AI大模型崛起:近几年,LLM(如GPT-4、LLaMA…...
周学习总结
这周继续学习了Java的知识点,还写了考查递归、递推与贪心的算法题。 算法小结 递归与递推一般是观察观察题干,分析题目的规律,可能还会用到分治算法,推导出一个合理的表达式,再使用函数递归来进行求解。 贪心在求解时…...
19.思科路由器:OSPF协议引入直连路由的实验研究
思科路由器:OSPF协议引入直连路由的实验研究 一、实验拓扑二、基本配置2.1、sw1的配置2.2、开启交换机三层功能三、ospf的配置3.1、R1的配置3.2、R2的配置3.3、重启ospf进程四、引入直连路由五、验证结果随着互联网技术的不断发展,路由器作为网络互联的关键设备,其性能与稳定…...
Zcanpro搭配USBCANFD-200U在新能源汽车研发测试中的应用指南(周立功/致远电子)
——国产工具链的崛起与智能汽车测试新范式 引言:新能源汽车测试的国产化突围 随着新能源汽车智能化、网联化程度的提升,研发测试面临三大核心挑战:多协议融合(CAN FD/LIN/以太网)、高实时性数据交互需求、复杂工况下…...
JSON的基础知识
文章目录 前言json协议的基本格式json 数组类型 的语法规则json协议报文的实例json常见的一些格式错误在gd32中使用cjson库小结 前言 json协议在互联网应用,物联网应用中都会用到。所谓工欲善其事必先利其器,我们需要学习了解json协议的具体格式…...
week2|机器学习(吴恩达)学习笔记
一、多维特征 1.1、什么是多维特征? 1)在我们的原始估计房价的版本中,我们只有一个变量: x x x 来预估 y y y 2)但是现在假设你也知道其他的参数变量,那么我们就可以引入多个参数来提高预测 y y y的准确…...
各类神经网络学习:(七)GRU 门控循环单元(上集),详细结构说明
上一篇下一篇LSTM(下集)GRU(下集) GRU(门控循环单元) 它其实是 R N N RNN RNN 和 L S T M LSTM LSTM 的折中版,有关 R N N RNN RNN 和 L S T M LSTM LSTM 请参考往期博客。 实际应用要比 …...
uniapp利用第三方(阿里云)实现双人视频/音频通话功能(附完整的项目代码)
要在UniApp中利用阿里云实现双人视频/音频通话功能,你需要使用阿里云的实时音视频服务(RTC)。以下是一个基本的实现步骤和示例代码。 基本的操作步骤 注册阿里云账号并开通RTC服务: 访问阿里云官网,注册账号并开通RTC服务。 获取AppID和AppKey: 在RTC控制台创建应用,…...
wsl2的centos7安装jdk17、maven
JDK安装 查询系统中的jdk rpm -qa | grep java按照查询的结果,删除对应版本 yum -y remove java-1.7.0-openjdk*检查是否删除 java -version 下载JDK17 JDK17,下载之后存到wsl目录下(看你自己)然后一键安装 sudo rpm -ivh jd…...
Android 单例模式全解析:从基础实现到最佳实践
单例模式(Singleton Pattern)是软件开发中常用的设计模式,其核心是确保一个类在全局范围内只有一个实例,并提供全局访问点。在 Android 开发中,单例模式常用于管理全局资源(如网络管理器、数据库助手、配置…...
Redis GEO
Redis GEO 引言 Redis GEO是Redis数据库中的一种高级功能,允许用户存储地理位置信息并执行基于地理空间查询的操作。本文将详细介绍Redis GEO的基本概念、使用方法以及在实际应用中的优势。 基本概念 GEO编码 GEO编码是指将地理位置信息(如经纬度&a…...
vulnhub-serile靶机通关攻略
下载地址:https://www.vulnhub.com/entry/serial-1,349/ 靶机安装特殊,附带安装参考文章:https://zhuanlan.zhihu.com/p/113887109 扫描IP地址 arp-scan -l扫描端口 nmap -p- 192.168.112.141访问80端口 线索指向cookie cookie是base64编…...
SAP-ABAP:OData 协议深度解析:架构、实践与最佳应用
OData 协议深度解析:架构、实践与最佳应用 一、协议基础与核心特性 协议定义与目标 定位:基于REST的开放数据协议,标准化数据访问接口,由OASIS组织维护,最新版本为OData v4.01。设计哲学:通过统一资源标识符(URI)和HTTP方法抽象数据操作,降低异构系统集成复杂度。核心…...
408 计算机网络 知识点记忆(3)
前言 本文基于王道考研课程与湖科大计算机网络课程教学内容,系统梳理核心知识记忆点和框架,既为个人复习沉淀思考,亦希望能与同行者互助共进。(PS:后续将持续迭代优化细节) 往期内容 408 计算机网络 知识…...
java学习笔记10——集合框架
枚举类的使用 Collection接口继承树 Map接口继承树 Collection 接口方法 总结: 集合框架概述 1.内存层面需要针对于多个数据进行存储。此时,可以考虑的容器有:数组、集合类2.数组存储多个数据方面的特点:> 数组一旦初始化,其长度就是确定的…...
埃文科技企业AI大模型一体机——昇腾体系+DeepSeek+RAG一站式解决方案
面对企业级市场海量数据资产与复杂业务场景深度耦合的刚需,埃文科技重磅推出基于华为昇腾算力DeepSeek大模型的企业一体机产品,提供DeepSeek多版本大模型一体机选择,为企业提供本地昇腾算力DeepSeek大模型RAG知识库的一体化解决方案ÿ…...
蓝桥杯---BFS解决FloofFill算法1---图像渲染
文章目录 1.算法简介2.题目概述3.算法原理4.代码分析 1.算法简介 这个算法是关于我们的floodfill的相关的问题,这个算法其实从名字就可以看出来:洪水灌溉,其实这个算法的过程就和他的名字非常相似,下面的这个图就生动的展示了这个…...
个人博客网站从搭建到上线教程
步骤1:设计个人网站 设计个人博客网站的风格样式,可以在各个模板网站上多浏览浏览,以便有更多设计网站风格样式的经验。 设计个人博客网站的内容,你希望你的网站包含哪些内容如你的个人基本信息介绍、你想分享的项目、你想分享的技术文档等等。 步骤2:选择开发技术栈 因…...
【FreeRTOS】裸机开发与操作系统区别
🔎【博主简介】🔎 🏅CSDN博客专家 🏅2021年博客之星物联网与嵌入式开发TOP5 🏅2022年博客之星物联网与嵌入式开发TOP4 🏅2021年2022年C站百大博主 🏅华为云开发…...
力扣每日一题:2712——使所有字符相等的最小成本
使所有字符相等的最小成本 题目示例示例1示例2 题解这些话乍一看可能看不懂,但是多读两遍就明白了。很神奇的解法,像魔术一样。 题目 给你一个下标从 0 开始、长度为 n 的二进制字符串 s ,你可以对其执行两种操作: 选中一个下标…...
Java EE(17)——网络原理——IP数据报结构IP协议解析(简述)
一.IP数据报结构 (1)版本:指明协议的版本,IPv4就是4,IPv6就是6 (2)首部长度:单位是4字节,表示IP报头的长度范围是20~60字节 (3)8位区分服务:实际上只有4位TOS有效,分别是最小延时,最…...
Pycharm运行时报“Empty suite”,可能是忽略了这个问题
问题:使用Pycharm运行testcases目录下的.py文件,报“Empty suite”,没有找到测试项。 排查过python解释器、pytest框架安装等等,依然报这个错,依然没找到,最后终端运行: pytest test_demo.py&a…...
Linux快速安装docker和docker-componse步骤
在 CentOS 7 上安装 Docker 和 Docker Compose 的步骤如下: 1. 安装 Docker 1.1. 更新系统 首先,确保你的系统是最新版本: sudo yum update -y1.2. 安装必要的包 安装 yum-utils,这是管理 YUM 源的工具: sudo yu…...
OP2177运算放大器:高性能模拟信号处理的关键元件
在现代电子系统中,模拟信号处理至关重要,运算放大器作为模拟电路的核心部件,其性能优劣直接影响系统的整体表现。OP2177 是一款具有卓越性能的运算放大器,在众多领域有着广泛应用。以下将结合相关资料,对 OP2177 进行全…...
paddle ocr
paddle ocr paddle ocr笔记准备工作referenceto onnx文本检测文本检测文字识别 paddle ocr笔记 准备工作 下载字典ppocr_keys_v1.txt,下标从1开始模型转换 reference paddlepaddle to onnx 下载模型,或者直接使用python跑一下并且把本地模型拿过来…...
通过动态获取项目的上下文路径来确保请求的 URL 兼容两种启动方式(IDEA 启动和 Tomcat 部署)下都能正确解析
背景 因为在不同的启动环境下,获取上下文路径的方式需要有所调整。在 IDEA 中运行时,路径是基于当前页面的 URL(如 index.html),而在 Tomcat 部署时,它是基于项目上下文路径(如 ssm-project&am…...
Spring Boot 整合 ElasticJob 分布式任务调度教程
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 Spring Boot 整合 ElasticJob 分布式任务调度教程 一、ElasticJob 简介 ElasticJob 是当当网开源的分布式任务调度解决方案,支持: …...
Django项目之订单管理part6(message组件和组合搜索组件)
一.前言 我们前面讲的差不多了,接着上节课讲,今天要来做一个撤单要求,我们可以用ajax请求,但是我这里介绍最后一个知识点,message组件,但是我会把两种方式都讲出来的,讲完这个就开始讲我们最重…...
[MySql] 多表关系, 多表查询
一. 多表关系 1.1 一对多 例如: 员工 - 部门表 (一个部门可以有多个员工) 并且在多的一方增加一个字段关联一的一方的主键. 外键约束: 物理外键 (使用 foreign key 定义外键关联另一张表的主键) 缺点: 影响增删改效率; 仅用于单节点, 不适用与集群; 易引发死锁, 性能低; …...
Open GL ES ->GLSurfaceView在正交投影下的图片旋转、缩放、位移
XML文件 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:o…...
一文详解QT环境搭建:Windows使用CLion配置QT开发环境
在当今的软件开发领域,跨平台应用的需求日益增长,Qt作为一款流行的C图形用户界面库,因其强大的功能和易用性而备受开发者青睐。与此同时,CLion作为一款专为C/C打造的强大IDE,提供了丰富的特性和高效的编码体验。本文将…...
MSTP和链路聚合
MSTP 802.1S --- MSTP --- 多生成树协议 --- 就是在RSTP基础上,再针对链路利用率低问题进行优化,可以和RSTP以及STP向下兼容。 实例 --- Instance --- 可以理解为一个V LAN或者多个VALN的集合。一个交换网络可以针对一个实例创建一棵树,起到…...
每天学一个 Linux 命令(8):ls
大家好,欢迎来到《每天掌握一个Linux命令》系列。在这个系列中,我们将逐步学习并熟练掌握Linux命令,今天,我们要学习的命令是ls。 01 什么是ls命令 在Linux系统中,ls命令是“list”的缩写,其英文全称为“list directory contents”,即“列出目录内容”。该命令非常实用…...
交换机、路由器、VLAN、单臂路由、三层交换、STP
华为模拟安装 1.依次安装wincap 2.wireshark 3.virtual box 4.ensp 一、设置 1.virtual box设置 2.计算机防火墙允许以上程序 3.eNSP设置 路由器:AR2240 交换机:S5700、CE12800 防火墙USG6000V 交换机 一、交换机工作原理 1、回顾 二层交换机…...
算法 | 2024最新算法:斑翠鸟优化算法原理,公式,应用,算法改进研究综述,matlab代码
基于斑翠鸟优化算法的原理、应用及改进研究综述 一、算法原理 斑翠鸟优化算法(Pied Kingfisher Optimizer, PKO)是2024年由Bouaouda等人提出的一种新型仿生智能优化算法,其灵感来源于斑翠鸟的捕食行为与共生关系。算法通过模拟斑翠鸟的栖息悬停、潜水捕鱼及与其他生物的共生…...
六十天Linux从0到项目搭建(第二十二天)(pipe、管道四种场景)
1 关于 pipe 系统调用的解析 int pipe(int pipefd[2]) 是 Unix/Linux 系统中用于创建匿名管道的系统调用。以下是关于管道特点的详细解释: 输出型参数 pipefd[2] 是输出型参数,调用成功后: pipefd[0] 存放管道的读取端文件描述符 pipefd[1…...
数据安全与网络安全——问答复习
目录 1、请简要分析勒索软件攻击的原理,并给出技术防护⽅案。 勒索软件攻击原理: 技术防护⽅案 2、举例数据安全问题 数据泄露 数据篡改 数据丢失 3、如何应对数据安全问题 技术层⾯ 管理层⾯ 4、软件漏洞 产⽣原因: 缓冲区溢出漏洞: 注⼊漏…...
ESP-01模块连接手机热点问题及解决方法
在使用ESP-01模块连接手机热点时,可能会遇到一些问题。本文将详细介绍如何解决这些问题,并分享最终通过将WiFi切换到2.4GHz成功解决问题的经验。 一、问题描述 在尝试使用ESP-01模块连接手机热点时,遇到了连接失败的问题。以下是操作过程中…...
go中锁的入门到进阶使用
Go 并发编程:从入门到精通的锁机制 引言:为什么需要锁? Go 语言以其天生支持并发的特性深受开发者喜爱,但并发带来的问题也不容小觑,比如数据竞争、并发安全等。如果多个 Goroutine 访问同一个变量,没有做…...
JS判断对象是否为空的方法
在 JavaScript 中,判断一个对象是否为空对象(即没有自身可枚举属性),可以通过以下方法实现: 方法 1:使用 Object.keys() javascript function isEmptyObject(obj) {// 确保是普通对象(排除 n…...
idea导入tomcat的jar
概述 对于老项目,未使用 Maven/Gradle 管理依赖的,在需要编译 Servlet/JSP 代码时,需要手动添加 Tomcat JAR 依赖(如 servlet-api.jar)方能进行编绎。 步骤: 1、找到 Tomcat 的 JAR 文件 进入 Tomcat 安…...
Linux 下安装和使用 Jupyter Notebook
Jupyter Notebook / Lab 是 Python 开发和数据分析中不可或缺的工具。为了避免环境污染,推荐使用虚拟环境方式安装并启动它。本教程将教你如何: 安装 Python、pip、venv使用虚拟环境安装 Jupyter汉化安装实用插件设置登录密码启动并远程访问编写一个一键…...
【Ubuntu常用命令】
1.将本地服务器文件或文件夹传输到远程服务器 文件 scp /data/a.txt administrator10.60.51.20:/home/administrator/ 文件夹 scp -r /data/ administrator10.60.51.20:/home/administrator/ 2.从远程服务器传输文件到本地服务器 scp administrator10.60.51.20:/data/a.txt /h…...
UR机械臂sim2real推荐包
推荐一个和ur机械臂配套的interface: ur_rtde Universal Robots RTDE C Interface — ur_rtde 1.6.0 documentation 也欢迎大家提供新想法和bug...