【问题标题】:How to use multi-threading on Hololens如何在 Hololens 上使用多线程
【发布时间】:2019-11-05 12:20:35
【问题描述】:

我们尝试在 Hololens 上使用多线程,但失败了。 因为我们不知道如何以及在附加线程中实现什么。

目前我们的应用程序正在主线程中运行许多操作,如果我们启动“实时流”(使用 WebcamTexture),全息图就不会再出现了。

首先我们想问一下,我们如何使用线程更有效地运行我们的部分照片捕获代码(见下文)?所以我们可以了解哪些部分在不同的线程中运行。

我们正在使用 Unity 2018.4.10f1

using UnityEngine;
using System.Linq;
using UnityEngine.XR.WSA.WebCam;

public partial class PhotocaptureFrame : MonoBehaviour
{

    public PhotoCapture photoCaptureObject = null;
    public GameObject quad;

    public static PhotocaptureFrame Instance { get; set; }

    private Texture2D imageTexture;
    private CameraParameters c;
    private Resolution cameraResolution;

    private void Start()
    {
        cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();

        PhotoCapture.CreateAsync(false, delegate (PhotoCapture captureObject)
        {
            photoCaptureObject = captureObject;

            //CameraParameters c = new CameraParameters();
            c.hologramOpacity = 0.0f;
            c.cameraResolutionWidth = cameraResolution.width;
            c.cameraResolutionHeight = cameraResolution.height;
            c.pixelFormat = CapturePixelFormat.BGRA32;

            captureObject.StartPhotoModeAsync(c, delegate (PhotoCapture.PhotoCaptureResult result)
            {
                photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
            });

        });

        Instance = this;
    }

    public void MakePhoto()
    {
        PhotoCapture.CreateAsync(false, delegate (PhotoCapture captureObject)
{
    photoCaptureObject = captureObject;

    captureObject.StartPhotoModeAsync(c, delegate (PhotoCapture.PhotoCaptureResult result)
    {
        photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
    });

});

    }

    public void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
    {

        Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First(); // Create our Texture2D for use and set the correct resolution
        Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);

        photoCaptureFrame.UploadImageDataToTexture(targetTexture);  // Copy the raw image data into our target texture

        imageTexture = targetTexture;       //Save image to new Texture to not loose it

        quad.GetComponent<Renderer>().material.mainTexture = imageTexture;     // Do as we wish with the texture such as apply it to a material, etc.
                                                                               //photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoModeEnd);


        // Clean up
        photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoModeEnd);
    }

    public void OnStoppedPhotoModeEnd(PhotoCapture.PhotoCaptureResult result)
    {
        photoCaptureObject.Dispose();
        photoCaptureObject = null;
        Debug.Log("Photo object disposed.");

    }
}

我们的预期输出是知道我们可以在不同的线程中运行哪些块,以及如何在 Hololens 上调用不同的线程。

感谢分配,感谢每一个帮助。

【问题讨论】:

  • 我觉得这个问题有点太接近于要求一个关于线程的教程或重构你的代码以优化你的线程使用。我建议阅读一些关于这个主题的教程,而不是依赖这个网站。如果您卡在线程的特定方面,这将是一个更合适的问题。看看这个:c-sharpcorner.com/article/… 和这个:docs.microsoft.com/en-us/dotnet/standard/threading/… 以及从中链接的相关文章。
  • 大部分事情不是在 async 在这里完成的吗?纹理创建等不能在线程中完成(至少不使用Texture2D 库)......顺便说一句,你知道imageTexture = targetTexture; //Save image to new Texture to not loose it 你实际上并没有创建一个新纹理,而只是存储一个参考,对吧?
  • 但有一件事:无需每次发送 photoCaptureObject 并重新创建它。只需创建一次,永远不要破坏它,这样可以节省一些资源......

标签: c# multithreading unity3d hololens


【解决方案1】:

虽然这不能直接回答你的问题,但我真的可以推荐这个插件:HololensCameraStream,它内部使用了MediaCapture 类。 帧是异步获取的,这意味着 Videocapture 本身本质上是在自己的线程中运行的。此外,与使用PhotoCapture 的方法相比,性能更好(您可以获得更多帧)。 您将在回调函数中获取每一帧。

由于此回调不在 Unity 主线程上运行,您将需要利用某种作业系统来调用您的 Unity 函数。我使用这个方便的脚本:https://github.com/PimDeWitte/UnityMainThreadDispatcher

如果这有帮助并且您还有其他问题,我可以添加有关如何设置的更多详细信息。

【讨论】:

    【解决方案2】:

    我建议您异步使用MediaCapture 类进行视频流捕获。在实际示例中,Microsoft SpectatorView 中的 HoloLensCamera 类使用 MediaCapture 类来访问来自 HoloLens 摄像头的视频流。在861线上,它声明了一个MediaCapture类的实例,并在接下来的代码中异步从摄像头获取视频帧。

    【讨论】:

      【解决方案3】:
              Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
      
              ...
      
              quad.GetComponent<Renderer>().material.mainTexture = imageTexture; 
      

      您只能在 Unity 的主线程上创建和分配纹理。正确且唯一的解决方案是调查WebCamTexture。您可能遇到了权限问题。

      【讨论】:

      • 嘿,谢谢,我们尝试了一些东西并恰好遇到了这个问题。遗憾的是,它不适用于WebCamTexture,因为它也是 Unity API 的一部分,因此在主线程上进行处理。但也许我错了。
      • 仔细阅读文档,如果您完全按照他们的示例进行操作,您将从网络摄像头获得加速直播。
      猜你喜欢
      • 2016-12-01
      • 2019-12-10
      • 1970-01-01
      • 2023-02-26
      • 2019-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-01
      相关资源
      最近更新 更多