如何将 EmguCV Image 转换为 Unity3D Sprite?
How to convert EmguCV Image to Unity3D Sprite?
我尝试在新的 Unity3D UI 系统上渲染来自 Emgu 相机捕获的图像。
到目前为止,我使用了这个存储库中的 ImageToTexture2d:
https://github.com/neutmute/emgucv/blob/3ceb85cba71cf957d5e31ae0a70da4bbf746d0e8/Emgu.CV/PInvoke/Unity/TextureConvert.cs
然后使用 Sprite.Create() 最终达到想要的结果。
但是!在我玩游戏 2-3 分钟后,似乎出现了一些大量的内存泄漏 运行 Unity 编辑器突然占用了大约 3GB 的 RAM,而开始时大约是 200MB。
我有两个疑点:
- (可能性更大)我使用的方法并没有清理内存。它使用 InterOp 并创建一些不安全的指针 - 它闻起来有泄漏。
- 每帧运行的 Sprite.Create 都会在内存中保留旧精灵,不会将其删除。
你们是否知道将 Emgu 的图像转换为 Sprite/Texture(不使用 InterOp)的任何其他方法或我可以在 New Unity 的 UI 上显示它的任何其他方法。它必须是 Emgu 的图像,因为我也对从相机收到的图像进行了一些操作。
在此先感谢您的回复和帮助。 :D
在不了解大部分游戏的情况下,您是否正在破坏内存中创建的对象的可能复制品?
突然增加3GB是否与游戏中的任何行为有关?即使没有 activity,它会增加吗?
经过一些研究,我发现了问题所在,但没有时间描述它。我不知道每帧创建的纹理都保存在引擎中的某个地方。在从 Emgu Image 生成新的之前必须销毁它们。
这是我在项目中使用的部分代码:
//Capture used for taking frames from webcam
private Capture capture;
//Frame image which was obtained and analysed by EmguCV
private Image<Bgr,byte> frame;
//Unity's Texture object which can be shown on UI
private Texture2D cameraTex;
//...
if(frame!=null)
frame.Dispose();
frame = capture.QueryFrame();
if (frame != null)
{
GameObject.Destroy(cameraTex);
cameraTex = TextureConvert.ImageToTexture2D<Bgr, byte>(frame, true);
Sprite.DestroyImmediate(CameraImageUI.GetComponent<UnityEngine.UI.Image>().sprite);
CameraImageUI.sprite = Sprite.Create(cameraTex, new Rect(0, 0, cameraTex.width, cameraTex.height), new Vector2(0.5f, 0.5f));
}
public static Texture2D ArrayToTexture2d(Image<Rgb, byte> picture) {
Array bytes = picture.ManagedArray;
int h = bytes.GetLength(0);
int w = bytes.GetLength(1);
Texture2D t2d = new Texture2D(w, h);
double r, b, g;
for (int heigth = 0; heigth < bytes.GetLength(0); heigth++)
{
for (int width = 0; width < bytes.GetLength(1); width++)
{
r = Convert.ToDouble(bytes.GetValue(heigth, width, 0));
g = Convert.ToDouble(bytes.GetValue(heigth, width, 1));
b = Convert.ToDouble(bytes.GetValue(heigth, width, 2));
t2d.SetPixel(width, h - heigth - 1, new Color((float)r / 256, (float)g / 256, (float)b / 256, 1f));
}
}
t2d.Apply();
return t2d;
}
RawImage targetRawImage;
Image<Rgb, byte> scanned = new Image<Rgb, byte>("Assets/Textures/scanned.png");
Texture2D loaded = new Texture2D(scanned.Width, scanned.Height);
loaded.LoadImage(scanned.ToJpegData());
targetRawImage.texture = loaded;
我尝试在新的 Unity3D UI 系统上渲染来自 Emgu 相机捕获的图像。 到目前为止,我使用了这个存储库中的 ImageToTexture2d: https://github.com/neutmute/emgucv/blob/3ceb85cba71cf957d5e31ae0a70da4bbf746d0e8/Emgu.CV/PInvoke/Unity/TextureConvert.cs 然后使用 Sprite.Create() 最终达到想要的结果。
但是!在我玩游戏 2-3 分钟后,似乎出现了一些大量的内存泄漏 运行 Unity 编辑器突然占用了大约 3GB 的 RAM,而开始时大约是 200MB。
我有两个疑点:
- (可能性更大)我使用的方法并没有清理内存。它使用 InterOp 并创建一些不安全的指针 - 它闻起来有泄漏。
- 每帧运行的 Sprite.Create 都会在内存中保留旧精灵,不会将其删除。
你们是否知道将 Emgu 的图像转换为 Sprite/Texture(不使用 InterOp)的任何其他方法或我可以在 New Unity 的 UI 上显示它的任何其他方法。它必须是 Emgu 的图像,因为我也对从相机收到的图像进行了一些操作。
在此先感谢您的回复和帮助。 :D
在不了解大部分游戏的情况下,您是否正在破坏内存中创建的对象的可能复制品?
突然增加3GB是否与游戏中的任何行为有关?即使没有 activity,它会增加吗?
经过一些研究,我发现了问题所在,但没有时间描述它。我不知道每帧创建的纹理都保存在引擎中的某个地方。在从 Emgu Image 生成新的之前必须销毁它们。
这是我在项目中使用的部分代码:
//Capture used for taking frames from webcam
private Capture capture;
//Frame image which was obtained and analysed by EmguCV
private Image<Bgr,byte> frame;
//Unity's Texture object which can be shown on UI
private Texture2D cameraTex;
//...
if(frame!=null)
frame.Dispose();
frame = capture.QueryFrame();
if (frame != null)
{
GameObject.Destroy(cameraTex);
cameraTex = TextureConvert.ImageToTexture2D<Bgr, byte>(frame, true);
Sprite.DestroyImmediate(CameraImageUI.GetComponent<UnityEngine.UI.Image>().sprite);
CameraImageUI.sprite = Sprite.Create(cameraTex, new Rect(0, 0, cameraTex.width, cameraTex.height), new Vector2(0.5f, 0.5f));
}
public static Texture2D ArrayToTexture2d(Image<Rgb, byte> picture) {
Array bytes = picture.ManagedArray;
int h = bytes.GetLength(0);
int w = bytes.GetLength(1);
Texture2D t2d = new Texture2D(w, h);
double r, b, g;
for (int heigth = 0; heigth < bytes.GetLength(0); heigth++)
{
for (int width = 0; width < bytes.GetLength(1); width++)
{
r = Convert.ToDouble(bytes.GetValue(heigth, width, 0));
g = Convert.ToDouble(bytes.GetValue(heigth, width, 1));
b = Convert.ToDouble(bytes.GetValue(heigth, width, 2));
t2d.SetPixel(width, h - heigth - 1, new Color((float)r / 256, (float)g / 256, (float)b / 256, 1f));
}
}
t2d.Apply();
return t2d;
}
RawImage targetRawImage;
Image<Rgb, byte> scanned = new Image<Rgb, byte>("Assets/Textures/scanned.png");
Texture2D loaded = new Texture2D(scanned.Width, scanned.Height);
loaded.LoadImage(scanned.ToJpegData());
targetRawImage.texture = loaded;