【ARFoundation自学04】AR Tracked Image 图像追踪识别与对应类的调用

news2025/1/11 21:58:31

图像识别是很常用的AR功能!AR foundation 可以帮助我们轻松实现!

1.安装插件

首先还是在资源包中导入ARfoundation 。然后搭建基本的AR ARFoundation框架!

2.创建AR session 和XR origin结构!

3.然后在XR Origin 物体身上添加AR Tracker Image Manager组件!

这个组件主要负责实现目标图像的识别和追踪! 但是我们需要思考,识别那个图片,识别后让谁追踪图片!他的主要原理是,创建一个图像库Library(Serialized Library),把要被识别的图都放进去,将来所有在库里面的图都可以被单独识别!

然后,识别图片后,为了让我们能够看到追踪图片的视觉效果,AR Tracker Image Manager会为识别后的图像克隆一份Tracked Image Prefab 用于跟随识别到的图像一起运动(移动或者旋转)!如何创建一个Tracked Image Prefab ,我们后面再讲!

4.创建图像识别库

这个图像库,需要用户安装插件后,在Assets 仓库面板空白点右键-Create-XR-Reference Image Library ,然后点击创建的图像库,在右侧属性面板添加将来要被识别的图!

这些图将来都会可识别!

5.创建识别后追踪的预制体(UI、模型等)Tracked Image Prefab  

这个预制体是图像识别专用的,因此需要挂载AR Tracked Image 组件!任何物体挂在了这个组件都可以作为识别图像后的追踪预制体!

那么我们自己的模型放在那里才可以追踪图片呢?只需要放在搭载AR Tracked Image 组件的父物体下面即可!

例如创建一个空物体,挂载AR Tracked Image 组件。把我们的模型放在这个空物体的子物体下面即可!

6. 把创建好可识别图像库以及追踪预制体赋值给 AR Tracker Image Manager组件!完毕

最后 AR Tracker Image Manager组件!还有个属性Max Number Of Moving Image 是最大可跟踪的动态图像数量!

7.其他参数介绍

图像跟踪技术,是指通过图像处理技术对摄像头中拍摄到的2D图像进行定位,并对其姿态进行跟踪的技术。图像跟踪技术的基础是图像识别,图像识别是指识别和检测出数字图像或视频中对象或特征的技术,图像识别技术是信息时代的一门重要技术,其产生目的是为了让计算机代替人类去处理大量的图形图像及真实物体信息,因而成为其他许多重要技术的基

  1. 最大并发跟踪数(Max Simultaneous Tracked Images):

    指定同时能够被识别和跟踪的图像数量。由于图像跟踪较为耗能,限制此数值可以避免性能问题。

    2. 参考图像(Reference Image)    

  • 这些是您希望AR应用能够识别的特定2D图像。比如,一张海报或标志。您需要事先在Unity项目中定义这些图像作为资源。别2D图像的过程实际是一个特征值对比的过程,ARFoundation将从摄像头中获取的图像信息与参考图像库的图像特征点信息进行对比,存储在参考图像库中的用于对比的图像就叫做参考图像。一旦对比成功,真实环境中的图像将与参考图像库的参考图像建立对应关系,每一个真实2D图像的姿态信息也一并被检测。

      3.参考图像库(Reference Image Library)    :

参考图像库用来存储一系列的参考图像用于对比,每一个图像跟踪程序都必须有一个参考图像库,但需要注意的是,参考图像库中存储的实际是参考图像的特征值信息而不是原始图像,这有助于提高对比速度与鲁棒性。参考图像库越大,图像对比就会越慢,建议参考图像库的图像不要超过1000张。跟踪组件提供方(Provider)    ARFoundation是架构在底层SDK图像跟踪API之上的,也即是说ARFoundation并不具体负责图像识别过程的算法,它只提供一个接口,具体图像识别由算法提供方提供。

8.动态修改TrackedImageManager的状态

  • 在代码中,你可以访问TrackedImageManager实例并根据需要动态改变其行为。例如,你可以暂时禁用所有图像的跟踪,或者针对特定图像进行开关控制
    public class ImageTrackingController : MonoBehaviour
    {
        public TrackedImageManager trackedImageManager;
        
        public void DisableImageTracking()
        {
            if (trackedImageManager != null)
            {
                trackedImageManager.enabled = false; // 关闭图像跟踪
            }
        }
    
        public void EnableImageTracking()
        {
            if (trackedImageManager != null)
            {
                trackedImageManager.enabled = true; // 启用图像跟踪
            }
        }
    }

    8.多图像跟踪

对于多图像跟踪,你可能不只希望实例化一个Prefab,而是根据识别到的不同图像实例化不同的Prefab。这时,传统的方式是为每个图像在数据集中指定对应的Prefab。但ARFoundation本身并不直接支持每个图像直接关联不同Prefab,因此需要一些额外的编程逻辑来实现这一功能。

实现逻辑

编写自定义脚本

创建一个C#脚本,用于处理图像识别后的逻辑。在这个脚本中,你需要监听TrackedImageUpdated事件,该事件会在图像被识别或跟踪状态改变时触发。

using System.Collections; // 引入集合相关的命名空间,用于列表(List)和字典(Dictionary)等数据结构
using System.Collections.Generic;
using UnityEngine; // 引入Unity引擎的基本功能
using UnityEngine.XR.ARSubsystems; // 引入AR相关子系统的命名空间
using UnityEngine.XR.ARFoundation; // 引入ARFoundation命名空间,提供AR功能的支持
using TMPro; // 引入TextMeshPro文本组件支持

public class ImageTrackControl : MonoBehaviour // 定义一个新的类,继承自MonoBehaviour,这是Unity中脚本的基础类
{
    // 公开变量,用于在Inspector面板中指定图像识别的核心组件
    public ARTrackedImageManager MyImageManagerCom;

    // 定义字符串变量,用于存储当前状态信息
    string myString;

    // 引用TextMeshProUGUI组件,用于在界面上显示文本信息
    public TextMeshProUGUI textdis;
    public TextMeshProUGUI textdis2;

    // 创建一个列表,用来存储预先准备好的图像追踪预制体
    public List<GameObject> MyImagePre = new List<GameObject>();

    // 使用Dictionary存储每个跟踪图的ID与其对应的预制体GameObject
    public Dictionary<string, GameObject> DityprefabMap = new Dictionary<string, GameObject>();

    // 临时对象变量,用于存储实例化后的游戏对象
    GameObject tempobj;

    // 当此脚本所属的游戏对象被唤醒时调用
    private void Awake()
    {
        // 确保MyImageManagerCom有被指定,若未指定,则尝试从该脚本所挂载的游戏对象上获取ARTrackedImageManager组件
        if (MyImageManagerCom == null)
        {
            MyImageManagerCom = this.transform.GetComponent<ARTrackedImageManager>();
        }

        // 初始化字典,将图像名称与预制体关联起来
        // 注意:这里假设MyImagePre列表已经被正确填充了相应的预制体
        DityprefabMap.Add("a", MyImagePre[0]);
        DityprefabMap.Add("b", MyImagePre[1]);
        DityprefabMap.Add("c", MyImagePre[2]);
        DityprefabMap.Add("d", MyImagePre[3]);
        DityprefabMap.Add("e", MyImagePre[4]);
    }

    // 当脚本或其所属的游戏对象变为可用时调用
    private void OnEnable()
    {
        // 绑定ARTrackedImageManager的trackedImagesChanged事件,当跟踪到的图像发生变化时会调用MyImChanged方法
        if (MyImageManagerCom != null)
        {
            MyImageManagerCom.trackedImagesChanged += MyImChanged;
        }
    }

    // 当脚本或其所属的游戏对象变为不可用时调用
    private void OnDisable()
    {
        // 解绑ARTrackedImageManager的trackedImagesChanged事件,防止内存泄漏或在对象不可用时继续接收事件
        if (MyImageManagerCom != null)
        {
            MyImageManagerCom.trackedImagesChanged -= MyImChanged;
        }
    }

    // 自定义事件处理方法,响应ARTrackedImageManager的trackedImagesChanged事件
    private void MyImChanged(ARTrackedImagesChangedEventArgs obj)
    {
        // 输出日志,表明图像跟踪状态已改变
        Debug.Log("追踪的图像发生变化了,调用委托函数");

        // 遍历新增的图像
        foreach (var trackedImage in obj.added)
        {
            // 更新UI显示新增的图像名称
            textdis.text = "新增图像: " + trackedImage.referenceImage.name;

            // 根据图像的名称从字典中获取对应的预制体,并在该图像的位置和旋转状态下实例化
            tempobj = Instantiate(DityprefabMap[trackedImage.referenceImage.name], trackedImage.transform.position, trackedImage.transform.rotation, trackedImage.transform);

            // 更新UI显示已克隆的预制体名称
            textdis2.text = "克隆了对象" + DityprefabMap[trackedImage.referenceImage.name].name;
        }

        // 下面注释掉的部分原本用于处理更新和移除的图像,可以根据需要启用并实现相应逻辑
        // ...
        
        // 遍历移除的图像,这里只是记录了移除的信息,实际操作如销毁相关游戏对象的逻辑可以根据需求添加
        foreach (var trackedImage in obj.removed)
        {
            myString = "移除图像: " + trackedImage.referenceImage.name;
            Debug.Log("移除图像: " + trackedImage.name);
        }
    }
}

下面是一些关于上面代码中核心类和方法的详细解释:

没有调用过ARTrackedImageManager 类下面的相关方法,尤其是 trackedImagesChanged,他是什么意思呢,什么作用? 

trackedImagesChanged 是 ARFoundation 中 ARTrackedImageManager 类的一个事件(可以去复习C#中的委托和事件的使用)。这个事件在图像跟踪状态发生改变时被触发!就会调用这个事件委托的函数(自己定义的)
在程序中如何使用呢?

 trackedImageManager.trackedImagesChanged += OnTrackedImagesChanged;

其中 trackedImageManager 是AR Tracked Image Manager 组件的对应类变量。存储了你场景中的一个AR Tracked Image Manager 组件!

+= OnTrackedImagesChanged;

这个意思是这个  trackedImageManager.trackedImagesChanged ,组件调用了一个委托事件trackedImagesChanged(代表识别的物体有变化,不管是位置、旋转、还是内容都算),一旦有变化我就委托一个函数去执行一个事情。trackedImageManager.trackedImagesChanged+=OnTrackedImagesChanged;

OnTrackedImagesChanged;就是一个自己定义的函数,被委托了!下面是这个函数的标准定义

 private void OnTrackedImagesChanged(ARTrackedImagesChangedEventArgs eventArgs)
    {
        //具体事情
    }

函数里面有个形式参数,这个参数是必须带的,就像我让你去办一件事,去把车门打开,我得给你钥匙,这个钥匙就是形式参数 ARTrackedImagesChangedEventArgs eventArgs!

ARTrackedImagesChangedEventArgs eventArgs

ARTrackedImagesChangedEventArgs 是 ARFoundation 提供的一个类,它作为参数传递给 ARTrackedImageManagertrackedImagesChanged 事件处理方法。这个类封装了在图像跟踪状态发生改变时的所有相关信息,包括哪些图像被新增、哪些被更新以及哪些被移除。通过分析 eventArgs 参数,开发者可以得知当前跟踪图像集合的具体变化情况,并据此做出相应的逻辑处理,比如实例化或销毁游戏对象、更新UI、执行特定动画等。

ARTrackedImagesChangedEventArgs 类包含三个主要的属性:

  1. added: 这是一个 NativeArray<ARTrackedImage> 类型的集合,包含了所有新被识别和开始跟踪的图像。每一个 ARTrackedImage 对象代表一个被跟踪的图像,包含了图像的 ID、大小、位置、旋转等信息。

  2. updated: 同样是 NativeArray<ARTrackedImage> 类型,包含了所有已跟踪图像中状态有所更新的图像(比如位置、姿态的微小变动)。开发者可以通过这些信息来实时调整已存在的AR内容,确保与实际跟踪状态同步。

  3. removed: 包含了 NativeArray<ARTrackedImage> 类型的集合,表示那些不再被跟踪的图像,可能是由于图像离开视野、遮挡或是其他原因导致跟踪丢失。对于这些图像,开发者通常需要清理与其关联的任何游戏对象或资源,以避免内存泄漏或视觉混乱。

在实际应用中,通过检查和响应 eventArgs 的这三个集合,开发者可以灵活地管理AR体验中的图像跟踪逻辑,保证应用的动态性和响应性。

完整示例代码:

using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;

public class ImageTrackingEventHandler : MonoBehaviour
{
    public ARTrackedImageManager trackedImageManager;

    void Start()
    {
        // 确保ARTrackedImageManager组件已经附加到了某个游戏对象上
        if (trackedImageManager == null)
        {
            trackedImageManager = GetComponent<ARTrackedImageManager>();
        }

        // 订阅trackedImagesChanged事件
        if (trackedImageManager != null)
        {
            trackedImageManager.trackedImagesChanged += OnTrackedImagesChanged;
        }
    }

    // 当跟踪的图像集合发生变化时,此方法会被调用
    private void OnTrackedImagesChanged(ARTrackedImagesChangedEventArgs eventArgs)
    {
        // 遍历新增的图像
        foreach (var trackedImage in eventArgs.added)
        {
            Debug.Log("新增图像: " + trackedImage.name);
            // 这里可以添加实例化预设体或其他处理逻辑
        }

        // 遍历更新的图像
        foreach (var trackedImage in eventArgs.updated)
        {
            Debug.Log("更新图像: " + trackedImage.name);
            // 可以在这里根据需要更新图像相关联的游戏对象状态
        }

        // 遍历移除的图像
        foreach (var trackedImage in eventArgs.removed)
        {
            Debug.Log("移除图像: " + trackedImage.name);
            // 这里可以添加销毁相关联游戏对象的逻辑
        }
    }

    void OnDestroy()
    {
        // 当这个脚本被销毁时,取消订阅事件,防止内存泄漏
        if (trackedImageManager != null)
        {
            trackedImageManager.trackedImagesChanged -= OnTrackedImagesChanged;
        }
    }
}

9. 再来一份代码,实现图像不在被追踪是清除克隆的Image prefab

using UnityEngine; // 引入Unity基本库,提供游戏对象、组件、物理等基础功能
using UnityEngine.XR.ARFoundation; // 引入ARFoundation库,用于AR开发的核心功能
using UnityEngine.XR.ARSubsystems; // 引入AR子系统,提供低级AR支持
using System.Collections.Generic; // 引入通用集合类型,如List、Dictionary等

public class TrackedImageHandler : MonoBehaviour // 定义一个Unity组件类,可以挂载到游戏对象上
{
    public ARTrackedImageManager trackedImageManager; // 公开的ARTrackedImageManager组件引用,用于管理图像跟踪
    public GameObject imagePrefab; // 公开的GameObject预设体,当识别到图像时将克隆这个预设体

    private Dictionary<XRCameraImageId, GameObject> trackedObjects = new Dictionary<TrackableId, GameObject>(); // 私有的字典,用于存储跟踪图像ID与对应实例化游戏对象的关系

    void Start() // Unity生命周期方法,当游戏对象启动时调用
    {
        if (trackedImageManager == null) // 检查是否已经指定了trackedImageManager
        {
            trackedImageManager = FindObjectOfType<ARTrackedImageManager>(); // 如果没有指定,则尝试在场景中自动查找ARTrackedImageManager组件
        }

        if (trackedImageManager != null) // 确保找到了ARTrackedImageManager
        {
            trackedImageManager.trackedImagesChanged += OnTrackedImagesChanged; // 注册事件处理器,当跟踪图像变化时调用OnTrackedImagesChanged方法
        }
        else
        {
            Debug.LogError("ARTrackedImageManager not found in the scene."); // 如果找不到ARTrackedImageManager,打印错误信息
        }
    }

    void OnDestroy() // Unity生命周期方法,在游戏对象被销毁前调用
    {
        if (trackedImageManager != null) // 确保trackedImageManager仍然有效
        {
            trackedImageManager.trackedImagesChanged -= OnTrackedImagesChanged; // 解除事件注册,避免内存泄漏
        }
    }

    void OnTrackedImagesChanged(ARTrackedImagesChangedEventArgs eventArgs) // 处理图像跟踪状态变化的事件方法
    {
        foreach (var trackedImage in eventArgs.removed) // 遍历移除的图像
        {
            GameObject trackedObject;
            if (trackedObjects.TryGetValue(trackedImage.trackableId, out trackedObject)) // 尝试从字典中获取关联的GameObject
            {
                Destroy(trackedObject); // 销毁关联的GameObject
                trackedObjects.Remove(trackedImage.trackableId); // 从字典中移除该条目
            }
        }

        foreach (var trackedImage in eventArgs.added) // 遍历新增的图像
        {
            if (!trackedObjects.ContainsKey(trackedImage.trackableId)) // 确保这个图像还没有被处理过
            {
                GameObject newObject = Instantiate(imagePrefab, trackedImage.transform.position, trackedImage.transform.rotation); // 实例化预设体,并放置在图像的位置和旋转
                trackedObjects.Add(trackedImage.trackableId, newObject); // 记录新实例化对象与图像ID的关联
            }
        }

        foreach (var trackedImage in eventArgs.updated) // 遍历更新的图像(位置或状态改变)
        {
            GameObject trackedObject;
            if (trackedObjects.TryGetValue(trackedImage.trackableId, out trackedObject)) // 获取关联的GameObject
            {
                trackedObject.transform.position = trackedImage.transform.position; // 更新游戏对象的位置
                trackedObject.transform.rotation = trackedImage.transform.rotation; // 更新游戏对象的旋转
            }
        }
    }
}

其他部分读者根据前面的理解应该能看懂!

解释一下其中的 if (trackedObjects.TryGetValue(trackedImage.trackableId, out trackedObject)) { Destroy(trackedObject); trackedObjects.Remove(trackedImage.trackableId); }

这段代码的作用是从一个字典(trackedObjects)中查找与特定跟踪图像ID(trackedImage.trackableId)关联的游戏对象,并在找到后进行销毁和从字典中移除的操作。让我逐步解释每一部分:

  1. if (trackedObjects.TryGetValue(trackedImage.trackableId, out trackedObject)):

    • TryGetValue 是 Dictionary 类的一个方法,用于尝试从字典中获取与指定键(这里是 trackedImage.trackableId)相关联的值(即游戏对象 GameObject)。
    • 方法有两个参数:键(key,这里是 trackedImage.trackableId)和一个输出参数(out parameter),用于接收查找到的值。如果找到了对应的键值对,这个值会被输出到 out 参数中;如果没有找到,输出参数会被赋予类型的默认值(对于引用类型,如 GameObject,默认值是 null)。
    • 这行代码的意思是尝试从 trackedObjects 字典中查找 trackedImage.trackableId 对应的 GameObject,并将找到的对象赋值给 trackedObject 变量。如果找到,TryGetValue 方法会返回 true,让 if 条件成立,执行后续代码。
  2. Destroy(trackedObject);:

    • 如果 trackedObject 不为 null(即字典中找到了与之关联的游戏对象),Destroy 函数会被调用,用来销毁这个 GameObject 实例。在Unity中,Destroy 方法用于清理游戏对象及其所有的子对象,释放它们占用的资源。
  3. trackedObjects.Remove(trackedImage.trackableId);:

    • 在销毁了游戏对象之后,这行代码从 trackedObjects 字典中移除与 trackedImage.trackableId 关联的条目。这样做是为了保持字典的整洁,避免保留不再使用的键值对,也有助于内存管理。

综上所述,这段代码块旨在处理图像跟踪移除事件,当一个AR跟踪图像不再被识别或跟踪时,它会安全地销毁与该图像关联的任何游戏对象实例,并清理字典中的记录,确保系统资源得到合理释放和管理。

课堂代码示例(重点讲解了委托函数以及事件回调):
 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using UnityEngine.Events;

public class ImageARmanager : MonoBehaviour
{
    // 检测用户图片识别的状态,
    public ARTrackedImageManager SMImageARMg;
    public ARFaceManager SMImfACEARMg;
    public GameObject muban;

    public UnityEvent OneUserHanshu;
    
    //public UnityEvent oneCallvbackevent;
   private void OnEnable()
    {
        SMImageARMg.trackedImagesChanged += SMImageARMg_trackedImagesChanged1; ;
        SMImfACEARMg.facesChanged += SMImfACEARMg_facesChanged;
    }

    private void SMImageARMg_trackedImagesChanged1(ARTrackedImagesChangedEventArgs obj)
    {
       
    }

    private void SMImfACEARMg_facesChanged(ARFacesChangedEventArgs obj)
    {
        foreach (var oneImage in obj.added)
        {
            Debug.Log("人脸换了");
            OneUserHanshu.Invoke();
        }
    }

    private void SMImageARMg_trackedImagesChanged(ARTrackedImagesChangedEventArgs obj)
    {

        foreach (var oneImage in obj.added)
        {
            Debug.Log("有新图片进入摄像头");
            GameObject.Instantiate(muban, oneImage.transform.position, oneImage.transform.rotation, oneImage.transform);
            OneUserHanshu.Invoke();
        }
        foreach (var oneImage in obj.removed)
        {
            Debug.Log("有图片离开摄像头");


        }     

    }
    
    private void OnDisable()
    {
        SMImageARMg.trackedImagesChanged -= responsive;//卸载这个委托节省性能
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GIS之arcgis系列07:conda环境下安装arcpy环境

首先将python27环境下的“Desktop10.8.pth”拷贝到anaconda环境下。 路径如下&#xff08;仅参考&#xff09;&#xff1a; C:\Python27\ArcGIS10.8\Lib\site-packages\Desktop10.8.pth D:\Anaconda\Lib\site-packages 在anaconda prompt中穿创建一个新环境 conda create -…

flink standalone部署模式

standalone模式可以在单台机器以不同进程方式启动&#xff0c;也可以以多机器分布式方式启动。 任务的提交模式有三种&#xff1a;application mode、session model、per-job mode&#xff08;1.4x版本后过时&#xff09;。 注意区分任务的提交模式与集群的部署模式区别。 以…

idea从git拉取代码需要输入token问题解决

idea使用git 推送代码时&#xff0c;提示token问题&#xff0c;这是因为你的代码仓库是gitlab&#xff0c; 然后打开修改代码后推送时&#xff0c;会默认使用gitlab插件&#xff0c;所以提示输入token解决方式就是把gitlab插件取消使用这样就好了。 取消之后再进行拉取代码即可…

华为鲲鹏应用开发基础:鲲鹏处理器及关键硬件特性介绍(二)

1. 鲲鹏简介 1.1 鲲鹏处理器简介 鲲鹏处理器是华为自研的基于ARMv8指令集开发的数据中心级处理器 1.2 基于鲲鹏主板的多样化计算产品 1.3 基于鲲鹏920的华为TaiShan(泰山) 200服务器 1.3.1 TaiShan 2280服务器内部视图 1.3.2 TaiShan 2280服务器物理结构 1.3.3 TaiShan 2280服…

4_机械臂位姿求逆理论及代码计算

1、aubo arcs sdk poseInverse 使用例子 auto cur_pose rpc_cli->getRobotInterface(robot_name)->getRobotState()->getTcpPose();// 2.288083 0.035207 1.550335auto pose_inv rpc_cli->getMath()->poseInverse(cur_pose);//结果&#xff1a;0.118611 -0.57…

数据不归路?文件清理的后悔药,2个文件恢复技巧

手机已成为我们生活中不可或缺的重要工具&#xff0c;它不仅仅是一个通讯设备&#xff0c;更是我们存储个人信息、工作文件、照片和视频等宝贵资料的仓库。然而&#xff0c;生活中的意外总是难以预料&#xff0c;有时候我们可能会不小心删除重要的文件&#xff0c;或者因为手机…

【c语言】文件操作,解开你的疑惑

文件操作 为什么使用文件什么是文件文件的分类文件名 二进制文件和文本文件文件的打开与关闭流与标准流流标准流 文件指针文件的打开与关闭 文件的顺序读写文件的随机读写文件读取结束的判定文件缓冲区 为什么使用文件 我们程序运行的数据是运行在内存中的&#xff0c;当成程序…

在线课堂知识付费小程序源码系统 带完整的安装代码包以及搭建教程

系统概述 在线课堂知识付费小程序源码系统是基于当前主流技术栈开发的&#xff0c;支持微信小程序端的在线教育平台解决方案。它不仅包含了课程发布、在线学习、支付系统等基础功能&#xff0c;还融入了社区互动、用户管理、数据分析等高级特性&#xff0c;旨在打造一个全方位…

filezilla-server 1.8.1 设置

filezilla-server 1.8.1 设置&#xff1a; 1. 2. 3. 4. 其他不用配置&#xff0c; 5. 6. 7. 8. 9. 如果外网连不上 filezilla-server 提示无法连接到服务器&#xff0c; 多半是 filezilla-server 所在的电脑没有通过防火墙允许&#xff0c;打开 Windows defender 防…

万兴优转 v15 解锁版安装教程(全能音视频格式转换器)

前言 Wondershare UniConverter&#xff08;万兴优转&#xff09;国产全能音视频格式转换器。万兴格式转换器具有音视频格式转换、合并视频、视频压缩、视频编辑、视频录制、下载视频、元数据修复、VR视频转换、字幕编辑器、GIF制作、DVD刻录等一站式视频工具箱功能。万兴转换…

从文本文件中读取博客数据并将其提取到文件中

通常情况下我们可以使用 Python 中的文件操作来实现这个任务。下面是一个简单的示例&#xff0c;演示了如何从一个文本文件中读取博客数据&#xff0c;并将其提取到另一个文件中。 假设你的博客数据文件&#xff08;例如 blog_data.txt&#xff09;的格式 1、问题背景 我们需…

如何压缩jpg图片到200k以下?跟着我操作!

在现代社交媒体和网络分享的时代&#xff0c;经常需要上传和分享各种图片。然而&#xff0c;有时候大尺寸的JPEG图片可能会成为上传和分享的一道难题&#xff0c;特别是当需要在网络条件不佳或存储空间有限的情况下。为了解决这个问题&#xff0c;我们需要学会如何压缩jpg图片到…

鸿蒙轻内核M核源码分析系列二十 Newlib C

LiteOS-M内核LibC实现有2种&#xff0c;可以根据需求进行二选一&#xff0c;分别是musl libC和newlibc。本文先学习下Newlib C的实现代码。文中所涉及的源码&#xff0c;均可以在开源站点https://gitee.com/openharmony/kernel_liteos_m 获取。 使用Musl C库的时候&#xff0c…

什么是AIGC?AIGC是否会颠覆未来的内容生产模式?普通人如何利用好AI提高内容生产效率?

2024年是AI元年&#xff0c;正好我在AI公司里面工作&#xff0c;对AIGC有着几年的研究&#xff0c;接下来把我这对AIGC的学习经验毫无保留的给大家分享一下 AIGC 的简要介绍 在狭义上&#xff0c;AIGC是指利用AI自动生成内容的生产方式&#xff0c;比如自动写作、自动设计等。…

【机器学习】基于3D CNN通过CT图像分类预测肺炎

1. 引言 1.1. 研究背景 在医学诊断中&#xff0c;医生通过分析CT影像来预测疾病时&#xff0c;面临一些挑战和局限性&#xff1a; 图像信息的广度与复杂性&#xff1a; CT扫描生成的大量图像对医生来说既是信息的宝库也是处理上的负担。每组CT数据可能包含数百张切片&#xf…

金智易表通流程设置的若干问题

1、审批节点的审批人取应用权限组&#xff0c;权限组内任一人审批即可通过 在流程节点的主要配置环节&#xff0c;选择候选组 二、已审菜单要求看到自己审过的也能看到别人审过的&#xff0c;即能看到所有已审的记录 管理设置中取消按钮对流程的依赖&#xff0c;不根据流程审批…

汇编:数组数据传送

要在32位汇编中实现数组数据的传送&#xff0c;可以使用字符串操作指令 MOVS 以及其前缀 REP&#xff0c;可以高效地复制数组数据。 MOVS 指令是一种字符串操作指令&#xff0c;用于将数据从源地址移动到目标地址。MOVS 指令有不同的变种&#xff0c;可以处理不同大小的数据&a…

Mimio安装

mkdir -p /usr/local/develop/minio/bin mkdir -p /usr/local/develop/minio/bin wget https://dl.min.io/server/minio/release/linux-amd64/minio -O /usr/local/develop/minio/bin/minio 编辑脚本 启动脚本 vim /usr/local/develop/minio/start_minio.sh #!/bin/bash # 设…

HTML,CSS,JavaScript实例 —— 齿轮,按钮

文章目录 一、动态按钮二、CSS实例三、滚动的齿轮 一、动态按钮 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style type"text/css">html,body {background: black;height: 100%;displa…

如何在Bing搜索进行广告推广?2024年必应广告投放怎么做?【附开户攻略】

必应&#xff08;Bing&#xff09;作为全球领先的搜索引擎之一&#xff0c;拥有一个独特且庞大的用户群体&#xff0c;尤其在美国和欧洲市场&#xff0c;很多用户选择必应作为他们的主要搜索引擎。通过必应广告&#xff0c;企业可以触达那些在其他搜索引擎上难以接触到的潜在客…