PhotoCaputure 导致 Unity 中的内存泄漏
Posted
技术标签:
【中文标题】PhotoCaputure 导致 Unity 中的内存泄漏【英文标题】:PhotoCaputure causes memory leak in Unity 【发布时间】:2021-11-12 01:33:28 【问题描述】:我正在使用 unity 的 Photocapture Object 拍摄带有 hololens 的视频。 我根据官方的示例代码写了代码,但是我在更新函数中改变了过程,以获取多张图片而不是一张。
https://docs.unity3d.com/2018.4/Documentation/Manual/windowsholographic-photocapture.html
但是,当我运行此代码时,它最终会用完 pagefile.sys、内存不足并中止。 我搜索并发现大多数内存泄漏是由纹理 2d 引起的,但是在这段代码中,即使我省略了它们,它们也会发生。此外,在执行代码后,统一分析器不会显示内存使用量的任何逐渐增加。 可能是什么原因?如果您能告诉我,我将不胜感激。
using UnityEngine;
using System;
using System.Linq;
using UnityEngine.XR;
using UnityEngine.Windows.WebCam;
using System.Threading.Tasks;
using UnityEngine.Networking;
using System.Text;
using System.IO;
using System.Net;
using System.Collections;
using System.Collections.Generic;
public class photocap : MonoBehaviour
PhotoCapture PhotoCapture = null;
Texture2D targetTexture = null;
Resolution cameraResolution;
Renderer quadRenderer;
float dt = 0;
void Start()
cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
GameObject quad = GameObject.CreatePrimitive(PrimitiveType.Quad);
quad.transform.localScale = new Vector3(0.2f, 0.2f, 0.2f);
quadRenderer = quad.GetComponent<Renderer>() as Renderer;
quadRenderer.material = new Material(Shader.Find("Unlit/Texture"));
quad.transform.parent = this.transform;
quad.transform.localPosition = new Vector3(0.0f, 0.0f, 0.3f);
async void StartCapture()
PhotoCapture.CreateAsync(false, delegate (PhotoCapture captureObject)
PhotoCapture = captureObject;
CameraParameters cameraParameters = new CameraParameters();
cameraParameters.hologramOpacity = 0.0f;
cameraParameters.cameraResolutionWidth = cameraResolution.width;
cameraParameters.cameraResolutionHeight = cameraResolution.height;
cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;
PhotoCapture.StartPhotoModeAsync(cameraParameters, delegate (PhotoCapture.PhotoCaptureResult result)
PhotoCapture.TakePhotoAsync(OnCapturedPhotoToMemory);
);
);
void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
PhotoCapture.StopPhotoModeAsync(OnStoppedPhotoMode);
void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
PhotoCapture.Dispose();
PhotoCapture = null;
void Update()
dt += Time.deltaTime;
if (dt > 3)
dt = 0.0f;
StartCapture();
【问题讨论】:
【参考方案1】:我很确定您也希望/必须处理 photoCaptureFrame
!
否则存储的纹理将永远留在您的应用程序内存中。
void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
// TODO: Obviously you first would want to do something with the just captured image ...
photoCaptureFrame.Dispose();
PhotoCapture.StopPhotoModeAsync(OnStoppedPhotoMode);
还有一件事:
您当前正在根据过去的时间开始新的捕获。
如果拍照、处理数据和处理的时间超过该间隔会怎样?
您可能更希望仅在第一次捕获实际完全完成后才触发新的捕获延迟!
实际上,为什么还要一直创建、启动、停止和处理捕获?您可以坚持使用一个并始终重复使用它
private PhotoCapture _photoCapture = null;
private Texture2D targetTexture = null;
private Resolution cameraResolution;
private Renderer quadRenderer;
private float dt = 0;
private void Start()
cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
var quad = GameObject.CreatePrimitive(PrimitiveType.Quad);
quad.transform.localScale = new Vector3(0.2f, 0.2f, 0.2f);
quadRenderer = quad.GetComponent<Renderer>();
quadRenderer.material = new Material(Shader.Find("Unlit/Texture"));
targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
quadRenderer.material.mainTexture = targetTexture;
quad.transform.parent = transform;
quad.transform.localPosition = new Vector3(0.0f, 0.0f, 0.3f);
StartCapture();
private void StartCapture()
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
private void OnPhotoCaptureCreated(PhotoCapture captureObject)
_photoCapture = captureObject;
var cameraParameters = new CameraParameters
hologramOpacity = 0.0f,
cameraResolutionWidth = cameraResolution.width,
cameraResolutionHeight = cameraResolution.height,
pixelFormat = CapturePixelFormat.BGRA32
;
_photoCapture.StartPhotoModeAsync(cameraParameters, OnPhotoCaptureStarted);
private void OnPhotoCaptureStarted(PhotoCapture.PhotoCaptureResult result)
// Take the first picture
TakePhoto();
// or if you really want more delay
//Invoke(nameof(TakePhoto, 3f));
private void TakePhoto()
_photoCapture.TakePhotoAsync(OnCapturedPhotoToMemory);
private void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
// Don't all the time destroy and create textures
// simply upload the new data to the already existing image
photoCaptureFrame.UploadImageDataToTexture(targetTexture);
Debug.Log("Captured");
photoCaptureFrame.Dispose();
// without the overhead of stopping and disposing etc simply take the next image
TakePhoto();
// or if you really want more delay
//Invoke(nameof(TakePhoto, 3f));
【讨论】:
谢谢,我尝试添加 photoCaptureFrame.Dispose();但它仍然会泄漏内存。 @lain 这是你的全部代码吗?你到底在用捕获的图像做什么?因为目前您的代码根本没有显示...您只是将帧捕获到内存...但是为了什么? @lain 你也说the unity profiler does not show any gradual increase in memory usage after the code is executed
...那你怎么知道有内存泄漏?我无法使用答案底部的代码重现这一点......我只删除了在前一个完成之前尝试开始的照片捕获引起的错误
省略了其余代码以澄清问题。我的整个代码在以下链接上。我计划将照片发送到服务器进行 AI 处理,但我目前处于可视化阶段。 github.com/pacifinapacific/MR_sample/blob/main/PhotocapW.cs
为什么总是破坏和创造一个新的纹理?只需创建一次并使用 photoCaptureFrame.UploadImageDataToTexture(targetTexture);
将其更新为相同的纹理以上是关于PhotoCaputure 导致 Unity 中的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章