c# - 将 AcquireCameraImageBytes() 从 Unity ARCore 保存为图像存储

标签 c# android unity3d arcore

使用 unity 和新的 1.1 版 ARCore,API 公开了一些获取相机信息的新方法。但是,我找不到任何将其作为文件保存到本地存储的 jpg 文件的好例子。

ARCore 示例有一个很好的示例,可以检索相机数据,然后在此处对其进行处理:https://github.com/google-ar/arcore-unity-sdk/blob/master/Assets/GoogleARCore/Examples/ComputerVision/Scripts/ComputerVisionController.cs#L212并且在该类中有一些检索相机数据的示例,但没有关于保存该数据的内容。

我看过这个:How to take & save picture / screenshot using Unity ARCore SDK?它使用较旧的 API 方式获取数据,也没有真正详细说明保存。

我理想中想要的是一种通过 Unity 将 API 中的 Frame.CameraImage.AcquireCameraImageBytes() 中的数据转换为磁盘上存储的 jpg 格式的方法。

更新

从那以后,我主要通过在 ARCore github 页面上挖掘这个问题来让它工作:https://github.com/google-ar/arcore-unity-sdk/issues/72#issuecomment-355134812并在下面修改 Sonny 的答案,因此被接受是公平的。

如果其他人试图这样做,我必须执行以下步骤:

  1. 将回调添加到 Start 方法以在图像可用时运行您的 OnImageAvailable 方法:

    public void Start()
    {
        TextureReaderComponent.OnImageAvailableCallback += OnImageAvailable;
    }
    
  2. 将 TextureReader(来自随 SDK 提供的计算机视觉示例)添加到您的相机和脚本

  3. 您的 OnImageAvailable 应该看起来像这样:

    /// <summary>
    /// Handles a new CPU image.
    /// </summary>
    /// <param name="format">The format of the image.</param>
    /// <param name="width">Width of the image, in pixels.</param>
    /// <param name="height">Height of the image, in pixels.</param>
    /// <param name="pixelBuffer">Pointer to raw image buffer.</param>
    /// <param name="bufferSize">The size of the image buffer, in bytes.</param>
    private void OnImageAvailable(TextureReaderApi.ImageFormatType format, int width, int height, IntPtr pixelBuffer, int bufferSize)
    {
        if (m_TextureToRender == null || m_EdgeImage == null || m_ImageWidth != width || m_ImageHeight != height)
        {
            m_TextureToRender = new Texture2D(width, height, TextureFormat.RGBA32, false, false);
            m_EdgeImage = new byte[width * height * 4];
            m_ImageWidth = width;
            m_ImageHeight = height;
        }
    
        System.Runtime.InteropServices.Marshal.Copy(pixelBuffer, m_EdgeImage, 0, bufferSize);
    
        // Update the rendering texture with the sampled image.
        m_TextureToRender.LoadRawTextureData(m_EdgeImage);
        m_TextureToRender.Apply();
    
        var encodedJpg = m_TextureToRender.EncodeToJPG();
        var path = Application.persistentDataPath;
    
        File.WriteAllBytes(path + "/test.jpg", encodedJpg);
    }
    

最佳答案

在 Unity 中,应该可以将原始图像数据加载到纹理中,然后使用 UnityEngine.ImageConversion.EncodeToJPG 将其保存为 JPG。 .示例代码:

public class Example : MonoBehaviour
{
    private Texture2D _texture;
    private TextureFormat _format = TextureFormat.RGBA32;

    private void Awake()
    {
        _texture = new Texture2D(width, height, _format, false);
    }

    private void Update()
    {
        using (var image = Frame.CameraImage.AcquireCameraImageBytes())
        {
            if (!image.IsAvailable) return;

            // Load the data into a texture 
            // (this is an expensive call, but it may be possible to optimize...)
            _texture.LoadRawTextureData(image);
            _texture.Apply();
        }
    }

    public void SaveImage()
    {
        var encodedJpg = _texture.EncodeToJPG();
        File.WriteAllBytes("test.jpg", encodedJpg)
    }
}

但是,我不确定 TextureFormat 是否对应于适用于 Frame.CameraImage.AcquireCameraImageBytes() 的格式。 (我熟悉 Unity 但不熟悉 ARCore。)请参阅 Unity 关于 TextureFormat 的文档,以及它是否与 ARCore 的 ImageFormatType 兼容。

此外,测试代码的性能是否足以满足您的应用需求。

编辑:正如用户@Lece 所解释的那样,使用 File.WriteAllBytes 保存编码数据。我已经更新了上面的代码示例,因为我最初省略了该步骤。

编辑 #2:有关特定于 ARCore 的完整答案,请参阅问题帖的更新。此处的评论也可能有用 - Jordan 指定“主要部分是使用 computer vision sdk example here 中的纹理读取器”。

关于c# - 将 AcquireCameraImageBytes() 从 Unity ARCore 保存为图像存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49579334/

相关文章:

java - 离线读取和删除加密文件,无需使用 Activity 结果

c# - Unity C#无法从迭代器返回值。使用yield return语句返回一个值,或使用yield break结束迭代

c# - 无法加载文件或程序集 'WebGrease,版本 = 1.5.1.25624

c# - 如何使用 json.net 将数据表转换为 json 字符串?

java - 按下后退按钮时如何获取最后使用的 Fragment

android - 可重新排序 ListView :Multiple widgets used the same GlobalKey

c# - ASP.NET_SessionId cookie 未定义

c# - 在 Visual Studio 2010 中使用目标构建时收到大量警告

c# - 统一 AdMob - ClassNotFound : com. google.unity.ads.UnityAdListener

android - 统一。安卓。更新应用程序后保存文件消失