Unity ARCore动态增加识别图
项目需要,有两点要求说明一下
1.如果你的图片是下载生成的,那没什么问题
2.如果你的识别图是存储在APK包里的话需要调整图片属性:
代码如下:
using QFramework; using System; using System.Collections.Generic; using System.IO; using System.Text; using Unity.Jobs; using UnityEditor; using UnityEngine; using UnityEngine.XR.ARFoundation; using UnityEngine.XR.ARSubsystems; namespace UnityEngine.XR.ARFoundation.Samples { /// <summary> /// Adds images to the reference library at runtime. /// </summary> [RequireComponent(typeof(ARTrackedImageManager))] public class DynamicLibrary : MonoSingleton<DynamicLibrary> { [Serializable] public class ImageData { [SerializeField, Tooltip("The source texture for the image. Must be marked as readable.")] Texture2D m_Texture; public Texture2D texture { get => m_Texture; set => m_Texture = value; } [SerializeField, Tooltip("The name for this image.")] string m_Name; public string name { get => m_Name; set => m_Name = value; } [SerializeField, Tooltip("The width, in meters, of the image in the real world.")] float m_Width; public float width { get => m_Width; set => m_Width = value; } public AddReferenceImageJobState jobState { get; set; } } [SerializeField, Tooltip("The set of images to add to the image library at runtime")] ImageData[] m_Images; /// <summary> /// The set of images to add to the image library at runtime /// </summary> public ImageData[] images { get => m_Images; set => m_Images = value; } enum State { NoImagesAdded, AddImagesRequested, AddingImages, Done, Error } State m_State; string m_ErrorMessage = ""; StringBuilder m_StringBuilder = new StringBuilder(); private void Start() { //var pathName = Application.persistentDataPath + "/3.jpg"; //Debug.Log(pathName); //var bytes = ReadFile(pathName); //int width = Screen.width; //int height = Screen.height; //Texture2D texture = new Texture2D(width, height, TextureFormat.RGB24, false); //texture.LoadImage(bytes); //texture = SettingTexture(texture); //ImageData data = new ImageData(); //data.texture = texture; //data.name = "3Test"; //data.width = 0.5f; //m_Images[0] = data; manager = GetComponent<ARTrackedImageManager>(); } public void AddImageTracked(List<string> list_SavePath) { m_Images = new ImageData[list_SavePath.Count]; for (int i = 0; i < list_SavePath.Count; i++) { int width = Screen.width; int height = Screen.height; var bytes = ReadFile(list_SavePath[i]); Texture2D texture = new Texture2D(width, height, TextureFormat.RGB24, false); texture.LoadImage(bytes); texture = SettingTexture(texture); ImageData data = new ImageData(); data.texture = texture; data.name = i.ToString(); data.width = 0.5f; m_Images[i] = data; } m_State = State.AddImagesRequested; } public void AddImageTracked(List<string> list_SavePath,Dictionary<string,Sprite>dicImageTracked) { m_Images = new ImageData[list_SavePath.Count]; Debug.Log(list_SavePath.Count +" "+ dicImageTracked.Count); for (int i = 0; i < list_SavePath.Count; i++) { Debug.Log("SavePath "+list_SavePath[i]); } foreach (var item in dicImageTracked) { Debug.Log(item.Key); } for (int i = 0; i < list_SavePath.Count; i++) { if (dicImageTracked.ContainsKey(list_SavePath[i])) { int width = dicImageTracked[list_SavePath[i]].texture.width; int height = dicImageTracked[list_SavePath[i]].texture.height; var bytes = dicImageTracked[list_SavePath[i]].texture.EncodeToPNG(); Texture2D texture = new Texture2D(width, height, TextureFormat.RGB24, false); texture.LoadImage(bytes); texture = SettingTexture(texture); ImageData data = new ImageData(); data.texture = texture; data.name = i.ToString(); data.width = 0.5f; m_Images[i] = data; } else Debug.LogError("Image Not SavePath"); } m_State = State.AddImagesRequested; } byte[] ReadFile(string filePath) { var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read); fs.Seek(0, SeekOrigin.Begin); var binary = new byte[fs.Length]; fs.Read(binary, 0, binary.Length); fs.Close(); return binary; } void OnGUI() { var fontSize = 50; GUI.skin.button.fontSize = fontSize; GUI.skin.label.fontSize = fontSize; float margin = 100; GUILayout.BeginArea(new Rect(margin, margin, Screen.width - margin * 2, Screen.height - margin * 2)); switch (m_State) { case State.NoImagesAdded: { //if (GUILayout.Button("Add images" + manager.trackables.count)) //{ // m_State = State.AddImagesRequested; //} break; } case State.AddingImages: { m_StringBuilder.Clear(); m_StringBuilder.AppendLine("Add image status:"); foreach (var image in m_Images) { m_StringBuilder.AppendLine($"\t{image.name}: {(image.jobState.status.ToString())}"); } // GUILayout.Label(m_StringBuilder.ToString()); break; } case State.Done: { // GUILayout.Label("All images added " + manager.trackables.count); break; } case State.Error: { GUILayout.Label(m_ErrorMessage); break; } } GUILayout.EndArea(); } void SetError(string errorMessage) { m_State = State.Error; m_ErrorMessage = $"Error: {errorMessage}"; } ARTrackedImageManager manager; void Update() { switch (m_State) { case State.AddImagesRequested: { if (m_Images == null) { SetError("No images to add."); break; } manager = GetComponent<ARTrackedImageManager>(); if (manager == null) { SetError($"No {nameof(ARTrackedImageManager)} available."); break; } // You can either add raw image bytes or use the extension method (used below) which accepts // a texture. To use a texture, however, its import settings must have enabled read/write // access to the texture. for (int i = 0; i < m_Images.Length; i++) { if (!m_Images[i].texture.isReadable) { Texture2D tex = SettingTexture(m_Images[i].texture); m_Images[i].texture = tex; } } foreach (var image in m_Images) { if (!image.texture.isReadable) { SetError($"Image {image.name} must be readable to be added to the image library."); break; } // else // Debug.LogError(" IsReadable = true "+image.name); } if (manager.referenceLibrary is MutableRuntimeReferenceImageLibrary mutableLibrary) { try { foreach (var image in m_Images) { // Note: You do not need to do anything with the returned JobHandle, but it can be // useful if you want to know when the image has been added to the library since it may // take several frames. image.jobState = mutableLibrary.ScheduleAddImageWithValidationJob(image.texture, image.name, image.width); } m_State = State.AddingImages; } catch (InvalidOperationException e) { SetError($"ScheduleAddImageJob threw exception: {e.Message}"); } } else { SetError($"The reference image library is not mutable."); } break; } case State.AddingImages: { // Check for completion var done = true; foreach (var image in m_Images) { if (!image.jobState.jobHandle.IsCompleted) { done = false; break; } } if (done) { m_State = State.Done; GameManager.Instance.finish = true; } break; } } } Texture2D SettingTexture( Texture2D texture) { //TextureImporter ti = (TextureImporter)TextureImporter.GetAtPath(AssetDatabase.GetAssetPath(texture)); //ti.isReadable = true; //AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(texture)); Texture2D tex = new Texture2D(texture.width, texture.height, TextureFormat.RGB24,false); byte[] data = texture.EncodeToPNG(); tex.LoadImage(data); Debug.Log(tex.isReadable); return tex; } } }