将 AcquireCameraImageBytes() 从 Unity ARCore 保存为图像存储
Save AcquireCameraImageBytes() from Unity ARCore to storage as an image
使用 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 并且在 class 中有一些检索相机数据的示例,但是没有什么可以保存该数据。
我看过这个: 它使用较旧的 API 获取数据的方式,也没有真正详细说明保存。
我理想中想要的是一种通过 Unity 将 API 中 Frame.CameraImage.AcquireCameraImageBytes()
中的数据转换为磁盘上存储的 jpg 的方法。
更新
从那以后,我主要通过在 ARCore github 页面上挖掘这个问题:https://github.com/google-ar/arcore-unity-sdk/issues/72#issuecomment-355134812 并在下面修改 Sonny 的回答,所以它被接受是公平的。
如果其他人试图这样做,我必须执行以下步骤:
当图像可用时,将 Start 方法的回调添加到 运行 您的 OnImageAvailable
方法:
public void Start()
{
TextureReaderComponent.OnImageAvailableCallback += OnImageAvailable;
}
将 TextureReader(来自随 SDK 提供的计算机视觉示例)添加到您的相机和脚本
您的 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 的完整答案,请参阅问题 post 的更新。此处的评论也可能有用 - Jordan 指定 "the main part was to use the texture reader from the computer vision sdk example here".
由于我对 ARCore 不熟悉,所以我将保持通用。
- 使用
LoadRawTextureData()
和 Apply()
将字节数组加载到您的 Texture2D
- 使用
EncodeToJPG()
对纹理进行编码
- 用
File.WriteAllBytes(path + ".jpg", encodedBytes)
保存编码后的数据
使用 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 并且在 class 中有一些检索相机数据的示例,但是没有什么可以保存该数据。
我看过这个:
我理想中想要的是一种通过 Unity 将 API 中 Frame.CameraImage.AcquireCameraImageBytes()
中的数据转换为磁盘上存储的 jpg 的方法。
更新
从那以后,我主要通过在 ARCore github 页面上挖掘这个问题:https://github.com/google-ar/arcore-unity-sdk/issues/72#issuecomment-355134812 并在下面修改 Sonny 的回答,所以它被接受是公平的。
如果其他人试图这样做,我必须执行以下步骤:
当图像可用时,将 Start 方法的回调添加到 运行 您的
OnImageAvailable
方法:public void Start() { TextureReaderComponent.OnImageAvailableCallback += OnImageAvailable; }
将 TextureReader(来自随 SDK 提供的计算机视觉示例)添加到您的相机和脚本
您的
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 的完整答案,请参阅问题 post 的更新。此处的评论也可能有用 - Jordan 指定 "the main part was to use the texture reader from the computer vision sdk example here".
由于我对 ARCore 不熟悉,所以我将保持通用。
- 使用
LoadRawTextureData()
和Apply()
将字节数组加载到您的 - 使用
EncodeToJPG()
对纹理进行编码
- 用
File.WriteAllBytes(path + ".jpg", encodedBytes)
保存编码后的数据
Texture2D