Как изменить этот скрипт для непрерывной съемки фотографий?

#c# #unity3d

#c# #unity3d

Вопрос:

Я могу сделать одну фотографию с помощью этого скрипта. Как я должен изменить этот скрипт для непрерывной съемки фотографий, чтобы отображать их в 3D плоскости? Я хочу постоянно передавать эту «targetTexture» некоторой функции.

 public class PhotoCaptureExample : MonoBehaviour
{
    PhotoCapture photoCaptureObject = null;

    // Use this for initialization
    void Start ()
    {
        PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
    }

    void OnPhotoCaptureCreated(PhotoCapture captureObject)
    {
        photoCaptureObject = captureObject;

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

        CameraParameters c = new CameraParameters();
        c.hologramOpacity = 0.0f;
        c.cameraResolutionWidth = cameraResolution.width;
        c.cameraResolutionHeight = cameraResolution.height;
        c.pixelFormat = CapturePixelFormat.BGRA32;

        captureObject.StartPhotoModeAsync(c, OnPhotoModeStarted);
    }

    void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
    {
        photoCaptureObject.Dispose();
        photoCaptureObject = null;
    }

    private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
    {
        if (result.success)
        {
            photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
        }
        else
        {
            Debug.LogError("Unable to start photo mode!");
        }
    }

    void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, 
        PhotoCaptureFrame photoCaptureFrame)
    {
        if (result.success)
        {
            // Create our Texture2D for use and set the correct resolution
            Resolution cameraResolution = PhotoCapture.SupportedResolutions
                .OrderByDescending((res) => res.width * res.height).First();
            Texture2D targetTexture = new Texture2D(cameraResolution.width, 
                cameraResolution.height);

            // Copy the raw image data into our target texture
            photoCaptureFrame.UploadImageDataToTexture(targetTexture);
            // Do as we wish with the texture such as apply it to a material, etc.
        }
        // Clean up
        photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
    }

    // Update is called once per frame
    void Update () 
    {           
    }
}
  

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

1. Возможно, это звучит как-то связано gamedev.stackexchange.com/q/158518/99708

Ответ №1:

Afaik вы не можете создавать новый TakePhotoAsync вызов для каждого кадра, но должны дождаться завершения текущего процесса. Это требует высокой производительности, и afaik также получает эксклюзивное разрешение на доступ к устройству камеры, поэтому любой другой вызов тем временем завершается неудачей.


Чтобы подождать со следующей фотографией до тех пор, пока одна из них не будет завершена в OnCapturedPhotoToMemory , вы могли бы просто вместо

 photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
  

вызовите следующую фотографию

 photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
  

Возможно, вам следует добавить условие выхода прямо перед ним, как private bool shouldStop подобное

 if(shouldStop)
{
    photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}
else
{
    photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
}
  

Однако имейте в виду, что это значительно замедлит работу вашего приложения! Поскольку большая часть Texture2D работы происходит в основном потоке и требует довольно высокой производительности!

Ответ №2:

Это далеко от совершенства, и я не тестировал это, но что-то вроде этого должно сработать. Однако вам может понадобиться цикл while внутри метода async void, чтобы он не замораживал ваше приложение.

 public class PhotoCaptureExample : MonoBehaviour
{
PhotoCapture photoCaptureObject = null;
bool capturing = false;

// Use this for initialization
void Start ()
{
    PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}

void OnPhotoCaptureCreated(PhotoCapture captureObject)
{
    photoCaptureObject = captureObject;

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

    CameraParameters c = new CameraParameters();
    c.hologramOpacity = 0.0f;
    c.cameraResolutionWidth = cameraResolution.width;
    c.cameraResolutionHeight = cameraResolution.height;
    c.pixelFormat = CapturePixelFormat.BGRA32;

    captureObject.StartPhotoModeAsync(c, OnPhotoModeStarted);
}

void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
    photoCaptureObject.Dispose();
    photoCaptureObject = null;
}

private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
    if (result.success)
    {
        capturing = true
        while(capturing)
        {
            try
            {
                photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
            }
            catch (Exception e)
            {
                // Do something
                capturing = false;
                // Clean up
                photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
            }
        }
    }
    else
    {
        Debug.LogError("Unable to start photo mode!");
    }
}

void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, 
    PhotoCaptureFrame photoCaptureFrame)
{
    if (result.success)
    {
        // Create our Texture2D for use and set the correct resolution
        Resolution cameraResolution = PhotoCapture.SupportedResolutions
            .OrderByDescending((res) => res.width * res.height).First();
        Texture2D targetTexture = new Texture2D(cameraResolution.width, 
            cameraResolution.height);

        // Copy the raw image data into our target texture
        photoCaptureFrame.UploadImageDataToTexture(targetTexture);
        // Do as we wish with the texture such as apply it to a material, etc.
    }
}

// Update is called once per frame
void Update () 
{
    if(!capturing)
    {
        // to ensure the photos are continuously being captured
        Start();
    }           
}
}
  

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

1. Возможно, вы захотите еще раз взглянуть на код. Он создает photoCaptureObject один раз. Затем устанавливает для захвата значение true и запускает цикл while. Это останавливает захват и удаляет photoCaptureObject только в случае исключения. Тогда метод Update вызывает его для повторного запуска только в том случае, если значение capture равно false. Что означало бы, что возникло исключение. Я что-то упускаю?

2. Да, извините, только что понял это 😉 проблема в любом случае: Afaik TakePhotoAsync будет сохранять эксклюзивное разрешение на чтение на устройстве, поэтому я думаю, что вам всегда нужно дождаться завершения одного процесса съемки, прежде чем начинать новый, и вы не сможете отправлять фотоснимки в спам с заданием takePhoto в каждом кадре.. в любом случае, определенно не в while цикле!