如何使用 vuforia 修复照片捕获错误,hololens 统一脚本

How to fix photocapture error with vuforia, script in unity for hololens

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

我得到的主要错误是:

Failed capturing photo (hr = 0xC00D3704)

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

The FocusManager singleton has not been initialized. UnityEngine.Debug:Assert(Boolean, String) HoloToolkit.Unity.Singleton`1:AssertIsInitialized() (at Assets/HoloToolkit/Common/Scripts/Singleton.cs:51) HoloToolkit.Unity.CanvasHelper:Start() (at Assets/HoloToolkit/Utilities/Scripts/CanvasHelper.cs:30)

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

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

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

感谢任何帮助!!

问题是:摄像头上的 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;

通过执行此操作,设备的相机是 "free",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.

有关