如何用vuforia修复光学捕获错误,为hololens统一编写脚本

问题描述 投票:1回答:1

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

我得到的主要错误是:

拍摄照片失败(小时= 0xC00D3704)

它为什么会发生?我如何解决它?

FocusManager单例尚未初始化。 UnityEngine.Debug:Assert(Boolean,String)HoloToolkit.Unity.Singleton`1:AssertIsInitialized()(在Assets / HoloToolkit / Common / Scripts / Singleton.cs:51)HoloToolkit.Unity.CanvasHelper:Start()(在Assets / HoloToolkit /工具/脚本/ CanvasHelper.cs:30)

在开始统一场景时也会发生错误,但我之前没有...

这是我正在使用的代码,放在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 ......

任何帮助表示赞赏!!

c# unity3d vuforia hololens
1个回答
2
投票

问题是:相机上的Vuforia的VuforiaBehaviour可以访问设备真正的相机硬件=>其他任何东西都不能同时使用它。


为了解决这个问题,你可以使用Vuforia的专用相机(只需在场景中放置一个新的GameObject,例如VuforiaCamera,并附加一个Camera组件以及一个VuforiaBehaviour

enter image description here

在Vuforia相机上设置Culling MaskNothing(我们不用那个相机渲染任何东西)和Depth到例如-2(较高的值呈现在顶部 - >将其置于所有其他相机之后)。

enter image description here

你必须这样做,因为否则Vuforia会自动将它添加到主摄像头(我们不想禁用它,因为我们没有看到任何东西)。通过手动将一个添加到场景中,Vuforia会自动使用该场景。

在您需要摄像机的场景中,您可以使用Holo-Tookit的原始相机(通常的MainCamera)。问题你不能完全依赖于脚本中的Camera.main,因为在运行时VuforiaBehaviour自动将其Camera标记为MainCamera ...( - _-)Vuforia ...所以另外我总是禁用并启用VuforiaBehaviour以及GameObject但是也许已经足够只能禁用和启用GameObject。至少在GameStart它应该被禁用我猜,直到所有依赖Camera.main完成。

然后你可以简单地禁用那个有VuforiaCameraVuforiaBehaviour

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(..

然后在回调中停止后再次启用ARCameraVuforiaBehaviour的对象)和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有关。

© www.soinside.com 2019 - 2024. All rights reserved.