Как исправить ошибку при фотосъемке с помощью vuforia, скрипт в единстве для гололинсов - PullRequest
1 голос
/ 26 марта 2019

Я пытаюсь сделать фотографию через Гололены с помощью скрипта Unity PhotoCapture. Я хочу использовать Vuforia Engine ARCamera для возможности увидеть реальность одновременно с тем, как я вижу созданный мной AR-GUI (для будущей функциональности).

Основная ошибка, которую я получаю:

Не удалось сделать снимок (hr = 0xC00D3704)

Почему это происходит? Как мне это исправить?

Синглтон FocusManager не был инициализирован. UnityEngine.Debug: Assert (Boolean, String) HoloToolkit.Unity.Singleton`1: AssertIsInitialized () (в Активы / HoloToolkit / Общие / Scripts / Singleton.cs: 51) HoloToolkit.Unity.CanvasHelper: Start () (в Активы / HoloToolkit / Утилиты / Scripts / 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 ...

Любая помощь приветствуется !!

1 Ответ

2 голосов
/ 26 марта 2019

Проблема в том, что Vuforia VuforiaBehaviour на камере удерживает доступ к реальному аппаратному обеспечению камеры устройства>> Пока что больше никто не может его использовать.


Для исправления этого вы можете использовать выделенную камеру для Vuforia (просто где-нибудь поместите новый GameObject, например, VuforiaCamera на сцену и прикрепите к ней компонент Camera, а также VuforiaBehaviour.

enter image description here

На Vuforia Camera установите Culling Mask на Nothing (мы ничего не визуализируем с этой камерой) и Depth на например. -2 (более высокие значения отображаются сверху -> поместите это позади всех остальных камер).

enter image description here

Вы должны сделать это, потому что в противном случае Vuforia автоматически добавляет его в основную камеру (которую мы не хотим отключать, потому что тогда мы ничего не видим). При добавлении одного к сцене Vuforia автоматически использует его вместо этого.

Везде, где вам нужна камера, конечно, вы используете оригинальную камеру из голо-туки (ваша обычная MainCamera). Проблема в том, что вы не можете полностью положиться на Camera.main в сценариях, потому что во время выполнения VuforiaBehaviour автоматически помечает Camera как MainCamera ... (-_-) Vuforia ... так что дополнительно я всегда отключал и включил VuforiaBehaviour вместе с GameObject, но, возможно, этого уже достаточно, чтобы только отключить и включить GameObject. По крайней мере, в GameStart его следует отключить, я полагаю, пока все, что зависит от Camera.main, не будет закончено.

Тогда вы можете просто отключить VuforiaCamera, на котором есть VuforiaBehaviour.

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);
}

Однако исключение также может быть связано с этой проблемой .

...