Как исправить ошибку photocapture с помощью vuforia, скрипта в unity для hololens

#c# #unity3d #vuforia #hololens

#c# #unity-игровой движок #vuforia #hololens

Вопрос:

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

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

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

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

Синглтон FocusManager не был инициализирован. UnityEngine.Отладка: утверждение (логическое значение, строка) HoloToolkit.Единство.Singleton`1:AssertIsInitialized() (в Assets/HoloToolkit/Common/Scripts/Singleton.cs:51) HoloToolkit.Единство.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

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

Комментарии:

1. Как был настроен FocusManager? это действительно unityscript? для меня это выглядит как обычный c #

2. честно говоря, я понятия не имею, что такое FocusManager и откуда он взялся: S Раньше он не отображался, но мог возникнуть, когда я вернулся к ARCamera из holotoolkits mixedRealityCamera… Это C #, но разве это несовместимо со скриптом unity (скриптом, созданным в unity)?

3. О, sry, я получил неправильный тег!!!

4. Хорошо, но он сообщает вам, что focusmanager не был настроен, это, кажется, первый пункт ошибки?

5. @BugFinder Да. После ошибки происходит 3 вызова FocusManager.AssertIsInitialized(); одного из методов SimpleSinglePointerSelector private void Start(). Один в методе CanvasHelper private void Start(). И еще один в CanvaseditorExtention, чтобы проверить, «есть ли у нас менеджер фокусировки в нашей сцене». Я не касался ни одного из них.

Ответ №1:

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


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

введите описание изображения здесь

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

введите описание изображения здесь

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

Везде в вашей сцене, где вам нужна камера, вы, конечно, используете оригинальную камеру из Holo-Took (вашу обычную MainCamera ). Проблема, на которую вы не можете полностью положиться Camera.main в скриптах, потому что во время выполнения VuforiaBehaviour также автоматически помечается его Camera как MainCamera … (-_-) Vuforia … таким образом, дополнительно я всегда отключал и включал VuforiaBehaviour вместе с GameObject, но, возможно, уже достаточно только отключить и включить GameObject. По крайней мере, при запуске игры это должно быть отключено, я думаю, до тех пор, пока не будет завершено все, на что полагается 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.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);
}
  

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

Комментарии:

1. Итак, у меня должно быть 2 камеры; одна описанная выше и одна основная камера?

2. ДА. Камере Vuforia вообще не нужно двигаться. Он используется только для доступа к реальной камере устройства.

3. Я все еще не до конца понимаю. Итак, у меня есть maincamera с тегом MainCamera, и у меня есть ARCamera со сценарием на ней с компонентами камеры и поведения vuforia? Установлен ли скрипт на нужную камеру? На какую камеру должен указывать холст?

4. Я добавил свою настройку. Я заметил, что на самом деле я в своем скрипте дополнительно включаю и отключаю VuforiaBehaviour сам, но это не должно иметь значения. На всех canvas и т.д., Где бы вам ни понадобилась камера, вы продолжаете использовать «обычную» главную камеру, как и раньше.. вы только добавляете дополнительную ARCamera с настройками, как на добавленном рисунке

5. Я все еще получаю Failed capturing photo (hr = 0xC00D3704) ошибку. Я пытался использовать только VuforiaBehaviour.Instance.gameObject.SetActive(false); , а затем только VuforiaBehaviour.Instance.enabled = false; , а затем оба из них, они действуют одинаково, так что, вероятно, не имеет значения, какой из них использовать в моем случае 🙂 Они были добавлены в start() (чтобы убедиться, что он не включен с самого начала), до photoCaptureObject.StartPhotoModeAsync и в конце в OnStoppedPhotoMode . Извините за медлительность, но чего я не понимаю?