将Unity ARCore中的AcquireCameraImageBytes()保存为存储为图像

使用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以及一些检索该类中相机数据的示例,但没有任何保存该数据的示例。

我见过这个: 如何使用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应该看起来像这样:

     ///  /// Handles a new CPU image. ///  /// The format of the image. /// Width of the image, in pixels. /// Height of the image, in pixels. /// Pointer to raw image buffer. /// The size of the image buffer, in bytes. 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的完整答案,请参阅问题post的更新。 这里的评论也可能有用 – Jordan指出“主要部分是使用来自计算机视觉sdk示例的纹理阅读器”。

由于我不熟悉ARCore,我将保持这种通用性。

  1. 使用LoadRawTextureData()Apply()将字节数组加载到Texture2D
  2. 使用EncodeToJPG()对纹理进行编码
  3. 使用File.WriteAllBytes(path + ".jpg", encodedBytes)保存编码数据