最新高通Vuforia 6-2-10版本 对应API 动态加载、卸载识别库 闪光灯 对焦 翻转摄像头 动态更改识别数量等...

本文主要是介绍最新高通Vuforia 6-2-10版本 对应API 动态加载、卸载识别库 闪光灯 对焦 翻转摄像头 动态更改识别数量等...,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

整理了下Vuforia 6-2-10 版本对应识别功能的函数


  • TrackableSettings类主要功能
    • 开启扩展追踪
    • 获取当前激活识别库名称列表
    • 激活指定的识别数据集
    • 关闭指定识别数据集
    • 动态载入识别数据集
    • 卸载所有识别数据集(识别库)
    • 设置同时识别Image的个数
    • 设置同时识别3D物体的个数

代码块如下

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using Vuforia;/// <summary>
/// 追踪功能设置类
/// </summary>
public class TrackableSettings : MonoBehaviour
{public const string Name = "TrackableSettings";static TrackableSettings() { }protected TrackableSettings() { }protected static volatile TrackableSettings instance = null;protected readonly object msyncRoot = new object();protected static readonly object mstaticSyncRoot = new object();public static TrackableSettings Instance{get{if (instance == null){lock (mstaticSyncRoot){if (instance == null) instance = new GameObject(Name).AddComponent<TrackableSettings>();}}return instance;}}/// <summary>/// 识别数据集所在的文件路径/// </summary>private string dataSetDirectoryPath = null;/// <summary>
/// 已经激活的识别数据集
/// </summary>protected Dictionary<string, string> mCurrentActiveDataSets = new Dictionary<string, string>();/// <summary>/// 所有数据集对应的路径/// </summary>protected Dictionary<string, string> mCurrentAllDataSets = new Dictionary<string, string>();/// <summary>/// 是否使用本地内置识别库/// </summary>public bool bLocal = false;/// <summary>/// 扩展追踪是否开启/// </summary>protected bool mExtTrackingEnabled = false;private void Awake(){//if (m_instance == null) m_instance = this;//if (gameObject.name == "GameObject") gameObject.name = Name;}private void Start(){Initialize();}private void Initialize(){dataSetDirectoryPath = Application.persistentDataPath + "/" + "DataDirectory"+"/";if (!Directory.Exists(dataSetDirectoryPath)){Directory.CreateDirectory(dataSetDirectoryPath);}}/// <summary>/// 获得扩展追踪开启状态/// </summary>/// <returns></returns>public bool IsExtendedTrackingEnabled(){return mExtTrackingEnabled;}/// <summary>/// 开启、关闭扩展追踪模式/// </summary>/// <param name="extTrackingEnabled">是否开启</param>public virtual void SwitchExtendedTracking(bool extTrackingEnabled){//返回可以访问当前所有跟踪的状态管理器实例。StateManager stateManager = TrackerManager.Instance.GetStateManager();// 我们遍历所有trackablebehaviours启动或停止扩展跟踪他们所代表的目标。bool success = true;foreach (var tb in stateManager.GetTrackableBehaviours()){if (tb is ImageTargetBehaviour){ImageTargetBehaviour itb = tb as ImageTargetBehaviour;if (extTrackingEnabled){if (!itb.ImageTarget.StartExtendedTracking()){success = false;Debug.LogError("扩展跟踪开始失败,对应目标: " + itb.TrackableName);}}else{itb.ImageTarget.StopExtendedTracking();}}else if (tb is MultiTargetBehaviour){MultiTargetBehaviour mtb = tb as MultiTargetBehaviour;if (extTrackingEnabled){if (!mtb.MultiTarget.StartExtendedTracking()){success = false;Debug.LogError("Failed to start Extended Tracking on Target " + mtb.TrackableName);}}else{mtb.MultiTarget.StopExtendedTracking();}}else if (tb is CylinderTargetBehaviour){CylinderTargetBehaviour ctb = tb as CylinderTargetBehaviour;if (extTrackingEnabled){if (!ctb.CylinderTarget.StartExtendedTracking()){success = false;Debug.LogError("Failed to start Extended Tracking on Target " + ctb.TrackableName);}}else{ctb.CylinderTarget.StopExtendedTracking();}}else if (tb is ObjectTargetBehaviour){ObjectTargetBehaviour otb = tb as ObjectTargetBehaviour;if (extTrackingEnabled){if (!otb.ObjectTarget.StartExtendedTracking()){success = false;Debug.LogError("Failed to start Extended Tracking on Target " + otb.TrackableName);}}else{otb.ObjectTarget.StopExtendedTracking();}}else if (tb is VuMarkBehaviour){VuMarkBehaviour vmb = tb as VuMarkBehaviour;if (extTrackingEnabled){if (!vmb.VuMarkTemplate.StartExtendedTracking()){success = false;Debug.LogError("Failed to start Extended Tracking on Target " + vmb.TrackableName);}}else{vmb.VuMarkTemplate.StopExtendedTracking();}}}mExtTrackingEnabled = success && extTrackingEnabled;}/// <summary>/// 获取当前激活识别库名称列表/// </summary>/// <returns></returns>public List<string> GetActiveDatasetNameList(){ObjectTracker tracker = TrackerManager.Instance.GetTracker<ObjectTracker>();List<DataSet> activeDataSets = tracker.GetActiveDataSets().ToList();List<string> tempList = new List<string>();for (int i = 0 ; i < activeDataSets.Count ; i++){string datasetPath = activeDataSets.ElementAt(i).Path;Debug.Log("datasetPath:" + datasetPath);string datasetName = datasetPath.Substring(datasetPath.LastIndexOf("/") + 1);Debug.Log("datasetName:" + datasetName);tempList.Add(datasetName.TrimEnd(".xml".ToCharArray()));}return tempList;}/// <summary>/// 激活指定的识别数据集/// </summary>/// <param name="datasetName">数据集名称或绝对路径</param>public virtual void ActivateDataSet(string datasetName){if (mCurrentActiveDataSets.ContainsKey(datasetName)){Debug.Log(string.Format("要激活的识别库:{0}已经加载", datasetName));return;} // objecttracker跟踪包含在数据集,提供了用于创建和方法的激活数据。ObjectTracker objectTracker = TrackerManager.Instance.GetTracker<ObjectTracker>();IEnumerable<DataSet> datasets = objectTracker.GetDataSets();IEnumerable<DataSet> activeDataSets = objectTracker.GetActiveDataSets();List<DataSet> activeDataSetsToBeRemoved = activeDataSets.ToList();// 1. 循环遍历所有的活动数据集并禁用它们foreach (DataSet ads in activeDataSetsToBeRemoved){objectTracker.DeactivateDataSet(ads);}// 在ObjectTracker运行时,不应该对数据集进行交换// 2. 所以首先要关闭trackerobjectTracker.Stop();// 3. 然后,查找新数据集,如果存在,激活它foreach (DataSet ds in datasets){if (ds.Path.Contains(datasetName)){objectTracker.ActivateDataSet(ds);mCurrentActiveDataSets.Add(datasetName, ds.Path);}}// 4. 最后重启traker.objectTracker.Start();}/// <summary>/// 关闭指定识别数据集/// </summary>/// <param name="datasetName">数据集名称或绝对路径</param>public virtual void DeactivateDateset(string datasetName){if (!mCurrentActiveDataSets.ContainsKey(datasetName)){Debug.Log(string.Format("要关闭的识别库:{0}不存在", datasetName));return;}ObjectTracker objectTracker = TrackerManager.Instance.GetTracker<ObjectTracker>();IEnumerable<DataSet> datasets = objectTracker.GetDataSets();IEnumerable<DataSet> activeDataSets = objectTracker.GetActiveDataSets();List<DataSet> activeDataSetsToBeRemoved = activeDataSets.ToList();List<DataSet> dataSetsToBeActive = new List<DataSet>();foreach (DataSet ads in activeDataSetsToBeRemoved){if (!ads.Path.Contains(datasetName)){dataSetsToBeActive.Add(ads);}objectTracker.DeactivateDataSet(ads);}objectTracker.Stop();foreach (DataSet ds in dataSetsToBeActive){objectTracker.ActivateDataSet(ds);}mCurrentActiveDataSets.Remove(datasetName);objectTracker.Start();}/// <summary>/// 载入识别数据集/// </summary>/// <param name="DataSetName">数据集名称</param>/// <param name="Local">是否是本地识别数据集</param>public virtual void LoadDataSet(string DataSetName, bool Local = true){ObjectTracker objectTracker = TrackerManager.Instance.GetTracker<ObjectTracker>();objectTracker.Stop();bool bLoadDataSet = false;DataSet mDataSet = null;if (VuforiaRuntimeUtilities.IsVuforiaEnabled()){objectTracker = TrackerManager.Instance.GetTracker<ObjectTracker>();mDataSet = objectTracker.CreateDataSet();if (!Local){bLoadDataSet = mDataSet.Load(dataSetDirectoryPath+DataSetName+".xml", VuforiaUnity.StorageType.STORAGE_ABSOLUTE);//绝对路径 一般用来加载网络下载的识别库(dat和xml文件)  }else{bLoadDataSet = mDataSet.Load(DataSetName);//本地预制的识别库  }}if (bLoadDataSet){mCurrentAllDataSets.Add(DataSetName, mDataSet.Path);UpdateImageTarget();Debug.Log("加载识别数据库成功并激活");if (objectTracker.ActivateDataSet(mDataSet)){mCurrentActiveDataSets.Add(DataSetName, mDataSet.Path);}else{Debug.Log(DataSetName + "激活失败");}}else{Debug.Log("加载识别数据库失败");}CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_TRIGGERAUTO);CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);objectTracker.Start();//开启识别器 (可以理解为摄像头)  }/// <summary>/// 更新ImageTarget上的信息/// </summary>public virtual void UpdateImageTarget(){ImageTargetBehaviour[] m_ImageTargetBehaviours = GameObject.FindObjectsOfType<ImageTargetBehaviour>();for (int i = 0 ; i < m_ImageTargetBehaviours.Length ; i++){ImageTargetBehaviour imageTargetBehaviour = m_ImageTargetBehaviours[i];imageTargetBehaviour.name = m_ImageTargetBehaviours[i].ImageTarget.Name + "Target";imageTargetBehaviour.gameObject.AddComponent<DefaultTrackableEventHandler>();imageTargetBehaviour.gameObject.AddComponent<TurnOffBehaviour>();}}/// <summary>/// 卸载所有识别数据集(识别库)/// </summary>public virtual void UnLoadAllDataSet(){ObjectTracker objectTracker = TrackerManager.Instance.GetTracker<ObjectTracker>();bool isVuforiaEnabled = VuforiaRuntimeUtilities.IsVuforiaEnabled();if (isVuforiaEnabled){//1. 关闭跟踪器objectTracker.Stop();//获取对应数据集合集(和激活数据集写法略有不同)IEnumerable<DataSet> dataSets = objectTracker.GetActiveDataSets();IEnumerator<DataSet> dEnumerator = dataSets.GetEnumerator();List<DataSet> listDataSet = new List<DataSet>();while (dEnumerator.MoveNext()){listDataSet.Add(dEnumerator.Current);}//关闭每一个数据集for (int i = 0 ; i < listDataSet.Count ; i++){Debug.Log("关闭对应数据集:" + listDataSet[i].Path);objectTracker.DeactivateDataSet(listDataSet[i]);}for (int i = 0 ; i < listDataSet.Count ; i++){Debug.Log("关闭对应数据集:" + listDataSet[i].Path);objectTracker.DestroyDataSet(listDataSet[i], false);}//管理所有可跟踪行为的状态StateManager stateManager = TrackerManager.Instance.GetStateManager();//ImageTargetBehaviour[] ImageTargetBehaviours = GameObject.FindObjectsOfType<ImageTargetBehaviour>();IEnumerable<TrackableBehaviour> IETrackableBehaviours = stateManager.GetTrackableBehaviours();//销毁对应创建的ImageTarget跟踪具体行为(就是在imagetarget上设置的参数)和销毁对应的GameObjectforeach (var tb in IETrackableBehaviours){stateManager.DestroyTrackableBehavioursForTrackable(tb.Trackable, true);}objectTracker.DestroyAllDataSets(true);Debug.Log("销毁识别数据成功");mCurrentActiveDataSets.Clear();mCurrentAllDataSets.Clear();}else{Debug.Log("销毁数据失败");}}/// <summary>/// 设置同时识别Image的个数/// </summary>/// <param name="TrackedCount"></param>public virtual void SetTrackedImageCount(int TrackedCount){VuforiaUnity.SetHint(VuforiaUnity.VuforiaHint.HINT_MAX_SIMULTANEOUS_IMAGE_TARGETS, TrackedCount);}/// <summary>/// 设置同时识别3D物体的个数/// </summary>/// <param name="TrackedCount"></param>public virtual void SetTrackedObjectCount(int TrackedCount){VuforiaUnity.SetHint(VuforiaUnity.VuforiaHint.HINT_MAX_SIMULTANEOUS_OBJECT_TARGETS, TrackedCount);}
}

  • FrameRateSettings类主要功能
    • 设置对应帧率

代码块如下:

using UnityEngine;
using Vuforia;/// <summary>
///帧率设置类
/// </summary>
public class FrameRateSettings : MonoBehaviour
{public const string Name = "FrameRateSettings";static FrameRateSettings() { }protected FrameRateSettings() { }protected static volatile FrameRateSettings instance = null;protected readonly object msyncRoot = new object();protected static readonly object mstaticSyncRoot = new object();public static FrameRateSettings Instance{get{if (instance == null){lock (mstaticSyncRoot){if (instance == null) instance = new GameObject(Name).AddComponent<FrameRateSettings>();}}return instance;}}void Awake(){//if (m_instance == null) m_instance = this;//if (gameObject.name == "GameObject") gameObject.name = Name;}void Start(){VuforiaARController.Instance.RegisterVuforiaStartedCallback(OnVuforiaStarted);}/// <summary>/// 高通全面启动的帧率设置回调/// </summary>private void OnVuforiaStarted(){//查询在unity中推荐的帧率(默认 AR或VR  省电 高帧数 四种模式)int targetFps = VuforiaRenderer.Instance.GetRecommendedFps(VuforiaRenderer.FpsHint.NONE);/*默认情况下,我们使用application.targetframerate设置推荐的帧速率。谷歌纸板不使用垂直同步,和OVR明确禁用它。如果开发商使用VSYNC的质量设置,他们也应该把他们的qualitysettings.vsynccount根据上面返回的值。例如:如果物体的FPS > 50 > vsynccount = 1;其他vsynccount = 2;*/if (Application.targetFrameRate != targetFps){Debug.Log("Setting frame rate to " + targetFps + "fps");Application.targetFrameRate = targetFps;}}}

  • CameraSettings类主要功能
    • 开启闪光灯
    • 开启自动对焦
    • 前后摄像机切换

代码块如下:

using UnityEngine;
using System.Collections;
using Vuforia;
/// <summary>
/// 摄像机功能设置类
/// </summary>
public class CameraSettings : MonoBehaviour
{public const string Name = "CameraSettings";static CameraSettings() { }protected CameraSettings() { }protected static volatile CameraSettings instance = null;protected readonly object msyncRoot = new object();protected static readonly object mstaticSyncRoot = new object();public static CameraSettings Instance{get{if (instance == null){lock (mstaticSyncRoot){if (instance == null) instance = new GameObject(Name).AddComponent<CameraSettings>();}}return instance;}}/// <summary>/// Vuforia是否完全启动/// </summary>private bool mVuforiaStarted = false;/// <summary>/// 自动对焦是否开启/// </summary>private bool mAutofocusEnabled = true;/// <summary>/// 闪光灯是否开启/// </summary>private bool mFlashTorchEnabled = false;/// <summary>/// 摄像头朝向/// </summary>private CameraDevice.CameraDirection mActiveDirection = CameraDevice.CameraDirection.CAMERA_DEFAULT;void Awake(){//if (m_instance == null) m_instance = this;//if (gameObject.name == "GameObject") gameObject.name = Name;}void Start(){VuforiaARController vuforia = VuforiaARController.Instance;//vuforia已经全面启动回调,包括相机和跟踪器。可以注册多个回调函数vuforia.RegisterVuforiaStartedCallback(OnVuforiaStarted);//停止和恢复的回调,这个是回复后重新让摄像机对焦(对应状态自动传入对应的bool值)vuforia.RegisterOnPauseCallback(OnPaused);}/// <summary>/// Vuforia完全启动回调/// </summary>private void OnVuforiaStarted(){mVuforiaStarted = true;//开启自动对焦SwitchAutofocus(true);}/// <summary>/// Vuforia停止和恢复的回调/// </summary>/// <param name="paused"></param>private void OnPaused(bool paused){bool appResumed = !paused;if (appResumed && mVuforiaStarted){// 恢复原来的对焦方式if (mAutofocusEnabled)CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);elseCameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);}else{//闪光灯状态更改 因为闪光灯会自动被操作系统关闭mFlashTorchEnabled = false;}}/// <summary>/// 闪光灯打开或或关闭状态/// </summary>/// <returns></returns>public bool IsFlashTorchEnabled(){return mFlashTorchEnabled;}/// <summary>/// 闪光灯开关/// </summary>/// <param name="ON">是否开启闪光灯</param>public virtual void SwitchFlashTorch(bool ON){if (CameraDevice.Instance.SetFlashTorchMode(ON)){Debug.Log("成功开启闪光灯 " + ON);mFlashTorchEnabled = ON;}else{Debug.Log("开启闪光灯失败 " + ON);mFlashTorchEnabled = false;}}public virtual bool IsAutofocusEnabled(){return mAutofocusEnabled;}/// <summary>/// 是否开启自动对焦/// </summary>/// <param name="ON">是否开启自动对焦</param>public virtual void SwitchAutofocus(bool ON){if (ON){if (CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO)){Debug.Log("成功开启连续对焦");mAutofocusEnabled = true;}else{// Fallback to normal focus modeDebug.Log("未能启用连续自动对焦,切换到正常对焦模式");mAutofocusEnabled = false;CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);}}else{Debug.Log("禁用连续自动对焦(启用正常对焦模式).");mAutofocusEnabled = false;CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);}}/// <summary>/// 强制触发一次对焦/// </summary>public virtual void TriggerAutofocusEvent(){CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_TRIGGERAUTO);// 恢复到原来的对焦模式StartCoroutine(RestoreOriginalFocusMode());}private IEnumerator RestoreOriginalFocusMode(){yield return new WaitForSeconds(1.5f);if (mAutofocusEnabled){CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);}else{CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);}}/// <summary>/// 前后摄像机切换/// </summary>/// <param name="camDir">摄像机方向</param>public virtual void SelectCamera(CameraDevice.CameraDirection camDir){if (RestartCamera(camDir)){mActiveDirection = camDir;// Upon camera restart, flash is turned offmFlashTorchEnabled = false;}}/// <summary>/// 转换摄像机需要把原来的摄像机状态关掉卸载然后重新初始化/// </summary>/// <param name="direction">摄像机方向</param>/// <returns></returns>public virtual bool RestartCamera(CameraDevice.CameraDirection direction){ObjectTracker tracker = TrackerManager.Instance.GetTracker<ObjectTracker>();if (tracker != null){tracker.Stop();}CameraDevice.Instance.Stop();CameraDevice.Instance.Deinit();if (!CameraDevice.Instance.Init(direction)){Debug.Log("初始化失败,指定的方向为: " + direction.ToString());return false;}if (!CameraDevice.Instance.Start()){Debug.Log("摄像机启动失败,指定的方向为: " + direction.ToString());return false;}if (tracker != null){if (!tracker.Start()){Debug.Log("Tracker重新启动失败");return false;}}return true;}/// <summary>/// 在IOS上翻转摄像头会出现摄像头上下颠倒的情况,在CameraDevice.Instance.Start()后调用次函数,反之忽略即可/// </summary>/// <returns></returns>IEnumerator Refresh(){yield return new WaitForEndOfFrame();Camera.main.transform.localEulerAngles = new Vector3(0, 0, 180.0f);}/// <summary>/// 是否为前置摄像头/// </summary>/// <returns></returns>public virtual bool IsFrontCameraActive(){return (mActiveDirection == CameraDevice.CameraDirection.CAMERA_FRONT);}}

  • InitErrorHandler类主要功能
    • Vuforia初始化时对应错误的回调(CustomLog自己封装的)

代码块如下:

using UnityEngine;
using System.Collections;
using Vuforia;
using Custom.Log;public class InitErrorHandler : MonoBehaviour
{private string key;void Awake(){VuforiaRuntime.Instance.RegisterVuforiaInitErrorCallback(OnInitError);if (Debuger.EnableLog){Debug.Log("+");}else{Debug.Log("-");}}private void OnInitError(VuforiaUnity.InitError error){if (error != VuforiaUnity.InitError.INIT_SUCCESS){ShowErrorMessage(error);}}private void CustomLog(string str){this.Log(str);}private void ShowErrorMessage(VuforiaUnity.InitError errorCode){switch (errorCode){//外部设备检测失败错误(摄像头)case VuforiaUnity.InitError.INIT_EXTERNAL_DEVICE_NOT_DETECTED:{string temp = "Vuforia初始化失败 " + "没有设备所需的外部硬件对接";CustomLog(temp);break;}// 没有输入密钥的错误case VuforiaUnity.InitError.INIT_LICENSE_ERROR_MISSING_KEY:{string temp = "Vuforia 密钥没有找到";CustomLog(temp);}break;// 输入的密钥无效的错误case VuforiaUnity.InitError.INIT_LICENSE_ERROR_INVALID_KEY:{key = VuforiaConfiguration.Instance.Vuforia.LicenseKey;if (key.Length > 10){string temp = "Vuforia 密钥无效:请申请有效的密钥";CustomLog(temp);}else{string temp = "Vuforia 密钥无效:密钥不完整";CustomLog(temp);}break;}case VuforiaUnity.InitError.INIT_LICENSE_ERROR_NO_NETWORK_TRANSIENT:{string temp ="无法接触服务器。请稍后再试";CustomLog(temp);break;}case VuforiaUnity.InitError.INIT_LICENSE_ERROR_NO_NETWORK_PERMANENT:{string temp ="没有可用的网络。请确保你与互联网连接。";CustomLog(temp);break;}case VuforiaUnity.InitError.INIT_LICENSE_ERROR_CANCELED_KEY:{key = VuforiaConfiguration.Instance.Vuforia.LicenseKey;string temp = "这款应用程序的许可密钥已被取消,可能不再使用";CustomLog(temp);break;}case VuforiaUnity.InitError.INIT_LICENSE_ERROR_PRODUCT_TYPE_MISMATCH:{key = VuforiaConfiguration.Instance.Vuforia.LicenseKey;string temp = "输入的密钥与对应的产品不相符";CustomLog(temp);}break;
//#if (UNITY_IPHONE || UNITY_IOS)case VuforiaUnity.InitError.INIT_NO_CAMERA_ACCESS:{string temp ="当在iOS设备上运行时,用户必须明确允许该应用访问摄像头。要恢复设备上的摄像头访问权限,请访问" +"Settings > Privacy > Camera > [萌伴小学堂] 然后开启权限";CustomLog(temp);break;}
//#endifcase VuforiaUnity.InitError.INIT_DEVICE_NOT_SUPPORTED:{string temp ="Vuforia初始化失败:此设备不支持";CustomLog(temp);break;}case VuforiaUnity.InitError.INIT_ERROR:{string temp = "Vuforia初始化失败:未知";CustomLog(temp);break;}}Debug.Log(errorCode);} //PRIVATE_METHODS}

这篇关于最新高通Vuforia 6-2-10版本 对应API 动态加载、卸载识别库 闪光灯 对焦 翻转摄像头 动态更改识别数量等...的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/695451

相关文章

最好用的WPF加载动画功能

《最好用的WPF加载动画功能》当开发应用程序时,提供良好的用户体验(UX)是至关重要的,加载动画作为一种有效的沟通工具,它不仅能告知用户系统正在工作,还能够通过视觉上的吸引力来增强整体用户体验,本文给... 目录前言需求分析高级用法综合案例总结最后前言当开发应用程序时,提供良好的用户体验(UX)是至关重要

更改docker默认数据目录的方法步骤

《更改docker默认数据目录的方法步骤》本文主要介绍了更改docker默认数据目录的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1.查看docker是否存在并停止该服务2.挂载镜像并安装rsync便于备份3.取消挂载备份和迁

你的华为手机升级了吗? 鸿蒙NEXT多连推5.0.123版本变化颇多

《你的华为手机升级了吗?鸿蒙NEXT多连推5.0.123版本变化颇多》现在的手机系统更新可不仅仅是修修补补那么简单了,华为手机的鸿蒙系统最近可是动作频频,给用户们带来了不少惊喜... 为了让用户的使用体验变得很好,华为手机不仅发布了一系列给力的新机,还在操作系统方面进行了疯狂的发力。尤其是近期,不仅鸿蒙O

什么是 Ubuntu LTS?Ubuntu LTS和普通版本区别对比

《什么是UbuntuLTS?UbuntuLTS和普通版本区别对比》UbuntuLTS是Ubuntu操作系统的一个特殊版本,旨在提供更长时间的支持和稳定性,与常规的Ubuntu版本相比,LTS版... 如果你正打算安装 Ubuntu 系统,可能会被「LTS 版本」和「普通版本」给搞得一头雾水吧?尤其是对于刚入

Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)

《Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)》:本文主要介绍Python基于火山引擎豆包大模型搭建QQ机器人详细的相关资料,包括开通模型、配置APIKEY鉴权和SD... 目录豆包大模型概述开通模型付费安装 SDK 环境配置 API KEY 鉴权Ark 模型接口Prompt

Spring Boot 中整合 MyBatis-Plus详细步骤(最新推荐)

《SpringBoot中整合MyBatis-Plus详细步骤(最新推荐)》本文详细介绍了如何在SpringBoot项目中整合MyBatis-Plus,包括整合步骤、基本CRUD操作、分页查询、批... 目录一、整合步骤1. 创建 Spring Boot 项目2. 配置项目依赖3. 配置数据源4. 创建实体类

windows端python版本管理工具pyenv-win安装使用

《windows端python版本管理工具pyenv-win安装使用》:本文主要介绍如何通过git方式下载和配置pyenv-win,包括下载、克隆仓库、配置环境变量等步骤,同时还详细介绍了如何使用... 目录pyenv-win 下载配置环境变量使用 pyenv-win 管理 python 版本一、安装 和

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

Java子线程无法获取Attributes的解决方法(最新推荐)

《Java子线程无法获取Attributes的解决方法(最新推荐)》在Java多线程编程中,子线程无法直接获取主线程设置的Attributes是一个常见问题,本文探讨了这一问题的原因,并提供了两种解决... 目录一、问题原因二、解决方案1. 直接传递数据2. 使用ThreadLocal(适用于线程独立数据)

Java中JSON字符串反序列化(动态泛型)

《Java中JSON字符串反序列化(动态泛型)》文章讨论了在定时任务中使用反射调用目标对象时处理动态参数的问题,通过将方法参数存储为JSON字符串并进行反序列化,可以实现动态调用,然而,这种方式容易导... 需求:定时任务扫描,反射调用目标对象,但是,方法的传参不是固定的。方案一:将方法参数存成jsON字