2025-01-01 NO2. XRHands 介绍
文章目录
- 软件配置
- 1 XR Hands 简介
- 2 XRHand
- 2.1 Pose
- 2.2 Handedness
- 3 XRHandJoint
- 3.1 XRHandJointID
- 3.2 XRHandJointTrackingState
- 4 XRHandSubsystem
- 4.1 数据属性
- 4.1.1 UpdateSuccessFlags
- 4.1.2 UpdateType
- 4.2 处理器管理:注册和注销
- 4.3 更新手部数据:`TryUpdateHands` 方法
- 4.3.1 检查运行,交由第三方处理
- 4.3.2 手部状态追踪与更新
- 4.3.3 数据预处理和处理器
- 4.3.4 动态更新和手势支持
- 4.3.5 回调处理
软件配置
- Unity 版本:Unity6000.0.26
- XRHands 版本:1.5.0
1 XR Hands 简介
XR Hands 包定义了允许从支持手部跟踪的设备访问手部跟踪数据的 API。要访问手部跟踪数据,还必须启用实现 XR 手部跟踪子系统的提供程序插件。
XR Hand 套件提供:
-
XR Hand Subsystem :定义用于手部跟踪数据的 XR 子系统接口。
-
OpenXR HandTracking feature:此功能为 OpenXR 提供程序插件实现
XRHandSubsystem。在项目中同时安装了 OpenXR 和 XR Hand 软件包,就可以访问手部数据。其他提供程序插件必须更新以实现XRHandSubsystem,然后才能在使用它们时访问手部数据。 -
Open XR Meta Aim Hand:此功能将来自 XR_FB_hand_tracking_aim 扩展的数据提供给 OpenXR 规范。此扩展提供基本的手势识别。
-
XR Hand:单个跟踪手的数据。
-
XR Hand Joint:手部单个关节或其他跟踪点的数据。
-
Meta Aim Hand:来自 Meta Aim 手 OpenXR 功能的捏合和瞄准手势数据。
注意:
XR Hands 包定义了用于手部跟踪的 API,但本身并未实现该功能。要在目标平台上使用手部跟踪,您还需要该平台的单独提供程序插件包,该插件包已更新以向 XR Hand Subsystem(该包定义的子系统)提供手部跟踪数据。
2 XRHand
代表来自 XRHandSubsystem 的手数据对象,用于管理和表示手的状态和关节信息。它包含了关于手的信息和操作,例如获取手部关节、手部位姿和手部跟踪状态。
该类不被直接创建,而是通过 XRHandSubsystem.leftHand 和 XRHandSubsystem.rightHand 属性来访问。
public struct XRHand : IEquatable<XRHand>
{// 获取手的根位姿,位于手腕部位。public Pose rootPose { get; }// 该手是左手还是右手public Handedness handedness { get; }// 当前手的根位姿和关节是否被追踪public bool isTracked { get; }// 返回指定 ID 的关节数据// 由于关节数据存储在本地的 NativeArray 中,调用此方法时,会获取到最新的手数据。public XRHandJoint GetJoint(XRHandJointID id) { ... }...
}
2.1 Pose
Pose 是 Unity 中用于表示物体在三维空间中的位置和旋转,封装了 Vector3 和 Quaternion 的数据结构,分别用于存储位置和旋转,适合用于表示游戏对象、虚拟角色、手部模型等在空间中的姿势。
public struct Pose : IEquatable<Pose>
{public Vector3 position; // 位置public Quaternion rotation; // 旋转// 将当前 Pose 应用到一个给定的 Pose/Transform 上,通常用于将 Pose 从一个坐标系转换到另一个坐标系public Pose GetTransformedBy(Pose lhs) { ... }public Pose GetTransformedBy(Transform lhs) { ... }// 公共属性public Vector3 forward { get; }public Vector3 right { get; }public Vector3 up { get; }public Vector3 forward { get; }
}
2.2 Handedness
用于表示左右手:
// Decompiled with JetBrains decompiler
// Type: UnityEngine.XR.Hands.Handedness
// Assembly: Unity.XR.Hands, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: A6E3BCB6-F905-44B3-8327-8AFFABC5770A
// Assembly location: P:\Unity Project\Learning\XRHands-Learning\Library\ScriptAssemblies\Unity.XR.Hands.dll#nullable disable
namespace UnityEngine.XR.Hands
{/// <summary>/// Denotes which hand this joint is on./// </summary>public enum Handedness{Invalid,Left,Right,}
}
3 XRHandJoint
表示 XR 中手部关节的结构体,封装了与手部关节相关的多种信息,例如关节的 位置、旋转、半径、线速度、角速度 等。
[StructLayout(LayoutKind.Sequential)]
public struct XRHandJoint : IEquatable<XRHandJoint>
{public XRHandJointID id { get; } // 关节唯一标识符public Handedness handedness { get; } // 属于哪只手public XRHandJointTrackingState trackingState { get; } // 关节追踪状态// 尝试获取该关节的半径(如果有)。// 返回 true 表示成功获取,false 表示未能获取到有效数据。// 成功时,radius 参数将被赋值为关节的半径。public bool TryGetRadius(out float radius) { ... }// 尝试获取该关节的 姿势(位置和旋转)。// 如果姿势数据有效,返回 true,并将姿势信息赋值给 pose 参数。// 如果无效,则返回 false 并将 pose 设置为 Pose.identity。public bool TryGetPose(out Pose pose) { ... }// 尝试获取该关节的 线速度。// 如果线速度数据有效,返回 true,并将线速度赋值给 linearVelocity 参数。// 如果无效,则返回 false,并将 linearVelocity 设置为 Vector3.zero。public bool TryGetLinearVelocity(out Vector3 linearVelocity) { ... }// 尝试获取该关节的 角速度。// 如果角速度数据有效,返回 true,并将角速度赋值给 angularVelocity 参数。// 如果无效,则返回 false,并将 angularVelocity 设置为 Vector3.zero。public bool TryGetAngularVelocity(out Vector3 angularVelocity) { ... }...
}
3.1 XRHandJointID
XR Hand 将手部关节分为 26 种,包括指关节、指尖、手腕和手掌。
XR Hand 使用 XRHandJointID 枚举类表示该 26 个 Joint:
// Decompiled with JetBrains decompiler
// Type: UnityEngine.XR.Hands.XRHandJointID
// Assembly: Unity.XR.Hands, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: A6E3BCB6-F905-44B3-8327-8AFFABC5770A
// Assembly location: P:\Unity Project\Learning\XRHands-Learning\Library\ScriptAssemblies\Unity.XR.Hands.dll#nullable disable
namespace UnityEngine.XR.Hands
{/// <summary>/// The ID of this joint./// </summary>public enum XRHandJointID{Invalid = 0,BeginMarker = 1,Wrist = 1,Palm = 2,ThumbMetacarpal = 3,ThumbProximal = 4,ThumbDistal = 5,ThumbTip = 6,IndexMetacarpal = 7,IndexProximal = 8,IndexIntermediate = 9,IndexDistal = 10, // 0x0000000AIndexTip = 11, // 0x0000000BMiddleMetacarpal = 12, // 0x0000000CMiddleProximal = 13, // 0x0000000DMiddleIntermediate = 14, // 0x0000000EMiddleDistal = 15, // 0x0000000FMiddleTip = 16, // 0x00000010RingMetacarpal = 17, // 0x00000011RingProximal = 18, // 0x00000012RingIntermediate = 19, // 0x00000013RingDistal = 20, // 0x00000014RingTip = 21, // 0x00000015LittleMetacarpal = 22, // 0x00000016LittleProximal = 23, // 0x00000017LittleIntermediate = 24, // 0x00000018LittleDistal = 25, // 0x00000019LittleTip = 26, // 0x0000001AEndMarker = 27, // 0x0000001B}
}
例如,在 HandVisualizer 示例场景中,Left Hand Tracking 物体上关联了手的所有 XRHandJointID。
3.2 XRHandJointTrackingState
表示正在跟踪的特定关节的值,分别有:
// Decompiled with JetBrains decompiler
// Type: UnityEngine.XR.Hands.XRHandJointTrackingState
// Assembly: Unity.XR.Hands, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: A6E3BCB6-F905-44B3-8327-8AFFABC5770A
// Assembly location: P:\Unity Project\Learning\XRHands-Learning\Library\ScriptAssemblies\Unity.XR.Hands.dllusing System;#nullable disable
namespace UnityEngine.XR.Hands
{[Flags]public enum XRHandJointTrackingState{None = 0, // 没有跟踪到数据Radius = 1, // 关节半径Pose = 2, // 关节姿势LinearVelocity = 4, // 关节线速度AngularVelocity = 8, // 关节角速度WillNeverBeValid = 16, // 永远失效,通常因为该关节不存在HighFidelityPose = 32, // 运行时精确追踪,而非基于推测或推算。通常来源于准确的传感器数据}
}
需要注意,该枚举类被标识为 [Flags],因此可以多选。
4 XRHandSubsystem
XRHandSubsystem 是一个抽象类或基类,通常由特定平台或设备的实现类继承和扩展,专门处理与手部追踪相关的数据,并提供框架来处理手部的状态、姿势、关节和手势等信息。
4.1 数据属性
public partial class XRHandSubsystem : SubsystemWithProvider<XRHandSubsystem, XRHandSubsystemDescriptor, XRHandSubsystemProvider>
{// 左、右手信息public XRHand leftHand { get; }public XRHand rightHand { get; } // 存储手部关节的布局信息(每个关节是否存在)public NativeArray<bool> jointsInLayout { get; }// 在最近一次手部数据更新过程中,左右手的哪些数据被成功更新。// 该属性每次手部数据更新时都会被更新。public UpdateSuccessFlags updateSuccessFlags { get; } // 与左、右手相关的常见手势的识别数据public XRCommonHandGestures leftHandCommonGestures { get; }public XRCommonHandGestures rightHandCommonGestures { get; }// 手部跟踪成功的回调事件public Action<XRHand> trackingAcquired;// 用于在手部数据的关节信息处理之前进行预处理。public Action<XRHandSubsystem, UpdateSuccessFlags, UpdateType> preprocessJoints;// 该回调会在手部数据更新时被调用。public Action<XRHandSubsystem, UpdateSuccessFlags, UpdateType> updatedHands;// 手部跟踪丢失的回调事件public Action<XRHand> trackingLost;...
}
回调的执行顺序为:
trackingAcquired -> preprocessJoints -> updatedHands -> trackingLost。
注意:
updatedHands 事件每帧执行两次,最大化手部数据的更新频率:
- 第一次:在 MonoBehaviour.Update 事件附近执行。
- 第二次:在 Application.onBeforeRender 事件附近执行。
4.1.1 UpdateSuccessFlags
包括以下:
/// <summary>
/// 在每次手部数据更新中,哪些手部数据被成功更新。
/// </summary>
[Flags]
public enum UpdateSuccessFlags
{// 没有任何数据被成功更新None = 0,// 左手根姿势数据已成功更新LeftHandRootPose = 1 << 0,// 左手关节数据已成功更新LeftHandJoints = 1 << 1,// 右手根姿势数据已成功更新RightHandRootPose = 1 << 2,// 右手关节数据已成功更新RightHandJoints = 1 << 3,// 所有有效的数据已成功更新All = LeftHandRootPose | LeftHandJoints | RightHandRootPose | RightHandJoints
}
4.1.2 UpdateType
/// <summary>
/// The timing of a hand update during a frame.
/// </summary>
public enum UpdateType
{// 类似 MonoBehaviour.Update 时机更新Dynamic,// 类似 Application.onBeforeRender 时机更新BeforeRender
}
4.2 处理器管理:注册和注销
XRHandSubsystem 支持在手部数据处理流程中插入自定义的处理器,通过 RegisterProcessor 和 UnregisterProcessor 方法来进行管理。
public partial class XRHandSubsystem : SubsystemWithProvider<XRHandSubsystem, XRHandSubsystemDescriptor, XRHandSubsystemProvider>
{...List<IXRHandProcessor> m_Processors = new List<IXRHandProcessor>();public void RegisterProcessor<TProcessor>(TProcessor processor)where TProcessor : class, IXRHandProcessor{if (processor == null)throw new ArgumentException("Processor cannot be null.", nameof(processor));m_Processors.Add(processor);m_Processors.Sort(CompareProcessors);}public void UnregisterProcessor<TProcessor>(TProcessor processor)where TProcessor : class, IXRHandProcessor{m_Processors.Remove(processor);}...
}
处理器需要实现 IXRHandProcessor 接口,负责处理和修改手部关节数据。每个处理器可以根据自己的优先级顺序进行数据处理,这个顺序由 callbackOrder 来决定。
例如,在 HandVisualizer 场景中,Hand Visualizer 物体上挂载的 HandProcessor.cs 脚本就是一个处理器,依据 ProcessorExampleMode 来对 Hands 进行平滑或翻转处理。
4.3 更新手部数据:TryUpdateHands 方法
在 XRHandProviderUtility.cs 脚本中,m_Subsystem.TryUpdateHands() 方法被 Update() 方法调用。因此,TryUpdateHands() 方法用于每帧更新 Hands 数据。
在 XRHandProviderUtility.cs 中的 OnUpdate() 和 OnBeforeRender() 方法分别调用了 Update() 方法,因此 m_Subsystem.TryUpdateHands() 方法每帧被更新 2 次,即 4.1 节中的注意内容。
4.3.1 检查运行,交由第三方处理
如果未运行,则直接返回。
同时,向手部数据提供者发送请求,更新左右手的数据。
public virtual unsafe UpdateSuccessFlags TryUpdateHands(UpdateType updateType)
{if (!running)return UpdateSuccessFlags.None;updateSuccessFlags = provider.TryUpdateHands(updateType,ref m_LeftHand.m_RootPose,m_LeftHand.m_Joints,ref m_RightHand.m_RootPose,m_RightHand.m_Joints);...
}
4.3.2 手部状态追踪与更新
public virtual unsafe UpdateSuccessFlags TryUpdateHands(UpdateType updateType)
{...// 清除手指的状态缓存,确保每次计算时使用的是最新的数据。XRFingerShapeMath.ClearFingerStateCache(Handedness.Left);XRFingerShapeMath.ClearFingerStateCache(Handedness.Right);// 检测左右手追踪状态,判断是否触发 trackingAcquired 或 trackingLostvar wasLeftHandTracked = m_LeftHand.isTracked;var success = UpdateSuccessFlags.LeftHandRootPose | UpdateSuccessFlags.LeftHandJoints;m_LeftHand.isTracked = (updateSuccessFlags & success) == success;if (!wasLeftHandTracked && m_LeftHand.isTracked)trackingAcquired?.Invoke(m_LeftHand);else if (wasLeftHandTracked && !m_LeftHand.isTracked)trackingLost?.Invoke(m_LeftHand);var wasRightHandTracked = m_RightHand.isTracked;success = UpdateSuccessFlags.RightHandRootPose | UpdateSuccessFlags.RightHandJoints;m_RightHand.isTracked = (updateSuccessFlags & success) == success;if (!wasRightHandTracked && m_RightHand.isTracked)trackingAcquired?.Invoke(m_RightHand);else if (wasRightHandTracked && !m_RightHand.isTracked)trackingLost?.Invoke(m_RightHand);...
}
对于左手:
-
wasLeftHandTracked:记录更新前左手的追踪状态。 -
success:判断左手根姿势和关节数据是否成功更新。 -
m_LeftHand.isTracked:根据success判断左手是否成功追踪。如果左手的追踪状态发生了变化(从未追踪到追踪,或从追踪中丧失),则触发
trackingAcquired或trackingLost回调。
右手同理。
4.3.3 数据预处理和处理器
public virtual unsafe UpdateSuccessFlags TryUpdateHands(UpdateType updateType)
{...// 对手部关节数据进行预处理preprocessJoints?.Invoke(this, updateSuccessFlags, updateType);// 每个处理器都对关节数据进行处理for (int processorIndex = 0; processorIndex < m_Processors.Count; ++processorIndex)m_Processors[processorIndex].ProcessJoints(this, updateSuccessFlags, updateType);...
}
4.3.4 动态更新和手势支持
如果更新类型是动态(Dynamic),并且手部数据提供者支持常见的手势数据,系统会更新不同的手势数据,例如:
- AimPose:目标对准姿势。
- GraspPose:抓握姿势。
- PinchPose:捏合姿势。
- GripPose:抓握姿势。
- …
对每种手势数据,XRHandSubsystem 会尝试从 provider 获取数据,并更新到对应的手势识别组件(m_LeftHandCommonGestures 和 m_RightHandCommonGestures)。如果数据不可用,则调用 Invalidate 方法使手势数据失效。
public virtual unsafe UpdateSuccessFlags TryUpdateHands(UpdateType updateType)
{...if (updateType == UpdateType.Dynamic && provider.canSurfaceCommonPoseData){if (subsystemDescriptor.supportsAimPose){if (provider.TryGetAimPose(Handedness.Left, out var aimPoseLeft))m_LeftHandCommonGestures.UpdateAimPose(aimPoseLeft);elsem_LeftHandCommonGestures.InvalidateAimPose();}// 其它手势处理类似:GraspPose, PinchPose, GripPose等...}...
}
4.3.5 回调处理
在数据更新后,通过 updatedHands 或 handsUpdated 回调通知外部系统手部数据已经更新。
updatedHands 是较新的回调方法,而 handsUpdated 已经被弃用,但仍然保持兼容。
public virtual unsafe UpdateSuccessFlags TryUpdateHands(UpdateType updateType)
{...if (updatedHands != null)updatedHands.Invoke(this, updateSuccessFlags, updateType);#pragma warning disable 618if (handsUpdated != null)handsUpdated.Invoke(updateSuccessFlags, updateType); // 弃用,但保持兼容
#pragma warning restore 618return updateSuccessFlags;
}
相关文章:
2025-01-01 NO2. XRHands 介绍
文章目录 软件配置1 XR Hands 简介2 XRHand2.1 Pose2.2 Handedness 3 XRHandJoint3.1 XRHandJointID3.2 XRHandJointTrackingState 4 XRHandSubsystem4.1 数据属性4.1.1 UpdateSuccessFlags4.1.2 UpdateType 4.2 处理器管理:注册和注销4.3 更新手部数据:…...
Java开发-后端请求成功,前端显示失败
文章目录 报错解决方案1. 后端未配置跨域支持2. 后端响应的 Content-Type 或 CORS 配置问题3. 前端 request 配置问题4. 浏览器缓存或代理问题5. 后端端口未被正确映射 报错 如下图,后端显示请求成功,前端显示失败 解决方案 1. 后端未配置跨域支持 …...
未来20年在大语言模型相关研究方向--大语言模型的优化与改进
未来20年在大语言模型相关研究方向 模型性能优化 模型架构创新:研究新型的模型架构,如探索更高效的Transformer变体、融合递归神经网络(RNN)和卷积神经网络(CNN)的优点,以提高模型的性能、可扩展性和适应性,满足不同应用场景对模型效率和效果的要求。高效训练算法:开…...
[react] 纯组件优化子
有组件如下,上面变化秒数, 下面是大量计算的子组件,上面每一秒钟变化一次,这时候子组件会不断重新渲染, 浪费资源 父组件如下 import React, { memo, useEffect, useMemo, useState } from react; import type { ReactNode, FC } from react; import HugeCount from ./Te; int…...
美观强大的文件保险库Chibisafe
简介 什么是 Chibisafe ? Chibisafe 是一款用 Typescript 编写的快速文件上传服务,非常实用。它接受文件、照片、文档以及您能想到的任何内容,并返回可共享的链接,供您发送给其他人。它易于使用、易于部署、免费且开源࿰…...
详细教程:SQL2008数据库备份与还原全流程!
数据的安全性至关重要,无论是操作系统、重要文件、磁盘存储,还是企业数据库,备份都是保障其安全和完整性的关键手段。拥有备份意味着即使发生误删、系统崩溃或病毒攻击等问题,也能迅速通过恢复功能解决,避免数据丢失带…...
HTML——49.header和footer标签
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>header和footer标签</title></head><body><!--header和footer标签:是html5中新标签--><!--header:定义文档的页眉,通常用来定义可见…...
【蓝桥杯选拔赛真题87】python输出字符串 第十五届青少年组蓝桥杯python选拔赛真题 算法思维真题解析
目录 python输出字符串 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python输出字符串 第十五届蓝桥杯青少年组python比赛选拔赛真题详细解析…...
OpenStack-Dashboard界面简单修改
OpenStack Dashboard界面替换图片 一、dashboard界面Logo的路径及文件 dashboard的Logo存放(在Controller节点)的路径: /usr/share/openstack-dashboard/openstack_dashboard/static/dashboard/img/涉及需要修改的文件(3个&…...
DevOps工程技术价值流:Ansible自动化与Semaphore集成
在DevOps的浪潮中,自动化运维工具扮演着举足轻重的角色。Ansible,作为一款新兴的自动化运维工具,凭借其强大的功能和灵活性,在运维领域迅速崭露头角。本文将深入探讨Ansible的特点、架构、工作原理,以及其应用场景&…...
【服务器】上传文件到服务器并训练深度学习模型下载服务器文件到本地
前言:本文教程为,上传文件到服务器并训练深度学习模型,与下载服务器文件到本地。演示指令输入,完整的上传文件到服务器,并训练模型过程;并演示完整的下载服务器文件到本地的过程。 本文使用的服务器为云服…...
第四届电子信息工程与数据处理(EIEDP 2025)
第四届电子信息工程与数据处理 2025 4th International Conference on Electronic Information Engineering and Data Processing 2025年1月17-19日 马来西亚 吉隆坡 重要信息 会议官网:www.eiedp.net 大会时间:2025年1月17-19日 大会地点&#…...
模型预测控制(MPC)算法介绍
模型预测控制(Model Predictive Control,MPC)是一种先进的控制策略,广泛应用于工业过程控制、机器人控制、电力系统等领域。它基于系统的模型,通过滚动优化来预测系统未来的行为,并据此确定当前的最优控制输…...
设计模式 创建型 建造者模式(Builder Pattern)与 常见技术框架应用 解析
建造者模式,又称生成器模式,是一种对象构建模式。它主要用于构建复杂对象,通过将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建出具有不同表示的对象。该模式的核心思想是将一个复杂对象的构建过程分解为多个简单的…...
嵌入式系统中C++的基本使用方法
大家好,今天主要给大家分享一下,最近操作C++代码的控制方法。 什么是构造函数?构造函数在对象实例化时被系统自动调用,仅且调用一次。 什么是析构函数?与构造函数相反, 在对象结束其生命周期时系统自动执行析构函数。 第一个:析构函数与构造函数区别 实例代码: #inclu…...
机器人C++开源库The Robotics Library (RL)使用手册(四)
建立自己的机器人3D模型和运动学模型 这里以国产机器人天机TR8为例,使用最普遍的DH运动学模型,结合RL所需的描述文件,进行生成。 最终,需要的有两个文件,一个是.wrl三维模型描述文件;一个是.xml运动学模型描述文件。 1、通过STEP/STP三维文件生成wrl三维文件 机器人的…...
在 uni-app 中使用 wxml-to-canvas 的踩坑经验总结
在 uni-app 中使用 wxml-to-canvas 的踩坑经验总结 wxml-to-canvas 是一款非常强大的小程序工具,可以将 WXML 转换为 Canvas 绘图,用于生成海报、分享图片等。将其应用于 uni-app 项目中,可以为多端开发带来极大的便利,但也有一些…...
视频智能翻译
i68,爱六八,链接你我他 EasyVideoTrans英文视频转换成中文视频 EasyVideoTrans简要 最快的英文视频转中文方案由B站多位程序员Up主共同协作开发开源的项目在线Demo:EasyVideoTrans前端项目:https://github.com/sutro-planet/easyvideotrans-frontend后端项目:https://github…...
《Python加解密小实验:探索数据加密与解密的世界》
铺垫(1)-源码 import hashlib source "你好" # print(hashlib.md5(source.encode()).hexdigest())# 文件加解密 with open(../文件引用/index.png, rb) as file:data file.read() # print(hashlib.md5(data).hexdigest())# SHA也是摘要算法…...
C高级day四shell脚本
1.思维导图 2.终端输入一个C源文件名(.c结尾)判断文件是否有内容,如果没有内容删除文件,如果有内容编译并执行该文件。 #!/bin/bashread -p "请输入一个.c脚本名:" n if [ -s "$n" ] thenecho $n…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...
保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...
