【问题标题】:How to fix photocapture error with vuforia, script in unity for hololens如何使用 vuforia 修复照片捕获错误,hololens 的统一脚本
【发布时间】:2019-03-26 11:12:04
【问题描述】:

我正在尝试使用我的 PhotoCapture 统一脚本通过 Hololens 拍照。我想使用 Vuforia Engine ARCamera,以便在看到我创建的 AR-GUI 的同时看到现实(用于未来的功能)。

我得到的主要错误是:

拍摄照片失败(hr = 0xC00D3704)

为什么会这样?我该如何解决?

FocusManager 单例尚未初始化。 UnityEngine.Debug:断言(布尔值,字符串) HoloToolkit.Unity.Singleton`1:AssertIsInitialized() (在 资产/HoloToolkit/Common/Scripts/Singleton.cs:51) HoloToolkit.Unity.CanvasHelper:Start() (在 Assets/HoloToolkit/Utilities/Scripts/CanvasHelper.cs:30)

也是启动unity场景的时候出现的错误,但是我之前没有出现过...

这是我正在使用的代码,放置在 ARCamera 上(还尝试了带有 vuforia 行为脚本的混合现实相机,但没有出现第二个错误)。另外,我想向借用此代码的人道歉,因为我不记得指向您网站的链接。

public class PhotoCaptureExample : MonoBehaviour
{
    PhotoCapture photoCaptureObject = null;
    Texture2D targetTexture = null;
    public string path = "";
    CameraParameters cameraParameters = new CameraParameters();

void Start()
{

}

void Update()
{
    if (Input.GetKeyDown("k"))
    {
        Debug.Log("k was pressed");

        Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
        targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);

        // Create a PhotoCapture object
        PhotoCapture.CreateAsync(false, delegate (PhotoCapture captureObject)
        {
            photoCaptureObject = captureObject;
            cameraParameters.hologramOpacity = 0.0f;
            cameraParameters.cameraResolutionWidth = cameraResolution.width;
            cameraParameters.cameraResolutionHeight = cameraResolution.height;
            cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;

            // Activate the camera
            photoCaptureObject.StartPhotoModeAsync(cameraParameters, delegate (PhotoCapture.PhotoCaptureResult result)
            {
                // Take a picture
                photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
            });
        });
    }
}

string FileName(int width, int height)
{
    return string.Format("screen_{0}x{1}_{2}.png", width, height, DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"));
}

void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
    // Copy the raw image data into the target texture
    photoCaptureFrame.UploadImageDataToTexture(targetTexture);

    Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();

    targetTexture.ReadPixels(new Rect(0, 0, cameraResolution.width, cameraResolution.height), 0, 0);
    targetTexture.Apply();

    byte[] bytes = targetTexture.EncodeToPNG();

    string filename = FileName(Convert.ToInt32(targetTexture.width), Convert.ToInt32(targetTexture.height));
    //save to folder under assets
    File.WriteAllBytes(Application.dataPath + "/Snapshots/" + filename, bytes);
    Debug.Log("The picture was uploaded");

    // Deactivate the camera
    photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}

void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
    // Shutdown the photo capture resource
    photoCaptureObject.Dispose();
    photoCaptureObject = null;
}
}

我似乎无法到达OnCapturedPhotoToMemory,或者它已经被方法调用中断了。现在再次尝试,代码偶尔不会注册我已经推送了k...

感谢任何帮助!

【问题讨论】:

  • FocusManager 被设置成什么?这真的是统一脚本吗?对我来说它看起来像普通的 c#
  • 老实说,我不知道 FocusManager 是什么或它来自哪里:S 它之前没有出现,但是当我从 holotoolkits mixedRealityCamera 改回 ARCamera 时可能已经发生了。 . 它是C#,但与统一脚本(统一编写的脚本)不兼容吗?
  • 哦,对不起,我打错标签了!!!
  • 好的,但是它告诉你焦点管理器尚未设置,这似乎是错误的第一点?
  • @BugFinder 是的。出现错误后,在 SimpleSinglePointerSelector 私有 void Start() 方法中对 FocusManager.AssertIsInitialized(); 进行了 3 次调用。 CanvasHelper 中的一个私有 void Start() 方法。还有一个在 CanvaseditorExtention 中检查“我们的场景中是否有焦点管理器”。这些我都没有碰过。

标签: c# unity3d vuforia hololens


【解决方案1】:

问题是:摄像头上的 Vuforia VuforiaBehaviour 持有设备真实摄像头硬件的访问权限 => 其他任何东西都不能同时使用它。


为了解决这个问题,您可以为 Vuforia 使用专用摄像头(只需在场景中的某个地方放置一个新的游戏对象,例如 VuforiaCamera 并附加一个 Camera 组件以及一个 VuforiaBehaviour 到它。

在 Vuforia 相机上将 Culling Mask 设置为 Nothing(我们不使用该相机渲染任何内容)并将 Depth 设置为例如-2(较高的值呈现在顶部 -> 将其放在所有其他相机后面)。

您必须这样做,否则 Vuforia 会自动将其添加到主摄像头(我们不想禁用它,因为这样我们什么都看不到)。通过手动向场景中添加一个,Vuforia 会自动使用该场景。

在场景中任何需要相机的地方,您当然都使用 Holo-Tookit 中的原始相机(您通常使用的 MainCamera)。问题您不能完全依赖脚本中的Camera.main,因为在运行时VuforiaBehaviour 会自动将其Camera 标记为MainCamera ... (-_-) Vuforia ... 所以另外我总是禁用并且启用了VuforiaBehaviour 和游戏对象,但也许只禁用和启用游戏对象就足够了。至少在 GameStart 应该禁用它,直到依赖 Camera.main 的所有内容都完成为止。

然后您可以简单地禁用带有VuforiaBehaviourVuforiaCamera

VuforiaBehaviour.Instance.gameObject.SetActive(false);

// Note: that part I'm just inventing since I did it different
// using reference etc. I hope vuforia does not destroy the Instance
// OnDisable .. otherwise you would need the reference instead of using Instance here
// but maybe it is already enough to just enable and disable the GameObject
VuforiaBehaviour.Instance.enabled = false;

通过这样做,设备的相机是“免费的”,PhotoCapture 现在可以使用它了。

PhotoCapture.StartPhotoModeAsync(....

如果您随后再次需要相机进行 vuforia,请先停止 PhotoCapture

PhotoCapture.StopPhotoModeAsync(..

然后在回调中停止后重新启用ARCamera(带有VuforiaBehaviour 的对象)和VuforiaBehaviour


类似

private void Awake()
{
    var cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
    targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);

    // Create a PhotoCapture object
    PhotoCapture.CreateAsync(false, captureObject =>
    {
        photoCaptureObject = captureObject;
        cameraParameters.hologramOpacity = 0.0f;
        cameraParameters.cameraResolutionWidth = cameraResolution.width;
        cameraParameters.cameraResolutionHeight = cameraResolution.height;
        cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;
    });
}

private void Update()
{
    // if not initialized yet don't take input
    if (photoCaptureObject == null) return;

    if (Input.GetKeyDown("k"))
    {
        Debug.Log("k was pressed");

        VuforiaBehaviour.Instance.gameObject.SetActive(false);

        // Activate the camera
        photoCaptureObject.StartPhotoModeAsync(cameraParameters, result =>
        {
           if (result.success)
           {
               // Take a picture
               photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
           }
           else
           {
               Debug.LogError("Couldn't start photo mode!", this);
           }
       });
    }
}

private static string FileName(int width, int height)
{
    return $"screen_{width}x{height}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png";
}

private void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
    // Copy the raw image data into the target texture
    photoCaptureFrame.UploadImageDataToTexture(targetTexture);

    Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();

    targetTexture.ReadPixels(new Rect(0, 0, cameraResolution.width, cameraResolution.height), 0, 0);
    targetTexture.Apply();

    byte[] bytes = targetTexture.EncodeToPNG();

    string filename = FileName(Convert.ToInt32(targetTexture.width), Convert.ToInt32(targetTexture.height));
    //save to folder under assets
    File.WriteAllBytes(Application.streamingAssetsPath + "/Snapshots/" + filename, bytes);
    Debug.Log("The picture was uploaded");

    // Deactivate the camera
    photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}

private void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
    // Shutdown the photo capture resource
    photoCaptureObject.Dispose();
    photoCaptureObject = null;

    VuforiaBehaviour.Instance.gameObject.SetActive(true);
}

但该异常也可能与this issue 有关。

【讨论】:

  • 所以我应该有 2 个摄像头;上面描述的一个和一个主摄像头?
  • 是的。 Vuforia 相机甚至根本不需要移动。仅用于访问设备真实摄像头。
  • 我还是不太明白。所以我有一个标记为 mainCamera 的主摄像头,我有一个带有脚本的 ARcamera,上面有摄像头和 vuforia 行为组件?脚本在正确的相机上吗?画布应该指向哪个相机?
  • 我添加了我的设置。我注意到我实际上在我的脚本中还启用和禁用了 VuforiaBehaviour 本身,但它不应该有所作为。在所有需要相机的画布等上,您可以像以前一样继续使用“普通”mainCamera ..您只需添加附加的 ARCamera 和添加图片中的设置
  • 我仍然收到Failed capturing photo (hr = 0xC00D3704) 错误。我试图只有VuforiaBehaviour.Instance.gameObject.SetActive(false);,然后只有VuforiaBehaviour.Instance.enabled = false;,然后它们两个都一样,所以在我的情况下使用哪一个可能并不重要:) 这些是在 start() 下添加的(以确保它不是从一开始就打开的),在photoCaptureObject.StartPhotoModeAsync 之前和OnStoppedPhotoMode 的末尾。对不起,我很慢,但我错过了什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-18
相关资源
最近更新 更多