Câmera de vídeo de foto na unidade

Ativar a capacidade de acesso à câmara

A capacidade "WebCam" deve ser declarada para uma aplicação para utilizar a câmara.

  1. No Editor de Unidade, aceda às definições dos jogadores navegando na página "Editar > Project Definições > Player"
  2. Selecione o separador "Windows Store"
  3. Na secção "Capacidades de publicação > Definições", verifique as capacidades > e microfone

Apenas uma única operação pode ocorrer com a câmara de cada vez. Pode verificar com que modo a câmara se encontra UnityEngine.XR.WSA.WebCam.Mode atualmente em Unity 2018 e mais cedo ou UnityEngine.Windows.WebCam.Mode em Unidade 2019 e mais tarde. Os modos disponíveis são fotografia, vídeo ou nenhum.

Captura de fotos

Espaço de nome (antes da Unidade 2019):UnityEngine.XR.WSA.WebCam
Espaço de nome (Unidade 2019 e mais tarde):UnityEngine.Windows. WebCam
Tipo:FotoCapture

O tipo PhotoCapture permite-lhe tirar fotografias ainda com a Câmara de Vídeo fotográfica. O padrão geral para usar o PhotoCapture para tirar uma foto é o seguinte:

  1. Criar um objeto PhotoCapture
  2. Crie um objeto CameraParameters com as definições desejada
  3. Iniciar o modo de fotografia via StartPhotoModeAsync
  4. Tire a foto que quiser.
    • (opcional) Interaja com esta imagem
  5. Pare o modo de fotografia e limpe os recursos

Configuração comum para PhotoCapture

Para todos os três usos, comece com os mesmos três primeiros passos acima

Comece por criar um objeto PhotoCapture

private void Start()
{
    PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}

Em seguida, guarde o seu objeto, desajeje os seus parâmetros e inicie o Modo Foto

private PhotoCapture photoCaptureObject = null;

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, false, OnPhotoModeStarted);
}

No final, também usará o mesmo código de limpeza apresentado aqui

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

Após estes passos, pode escolher que tipo de fotografia capturar.

Capture uma foto para um arquivo

A operação mais simples é capturar uma foto diretamente num ficheiro. A foto pode ser guardada como UM JPG ou um PNG.

Se tiver iniciado o modo fotográfico com sucesso, tire uma foto e guarde-a no disco

private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
    if (result.success)
    {
        string filename = string.Format(@"CapturedImage{0}_n.jpg", Time.time);
        string filePath = System.IO.Path.Combine(Application.persistentDataPath, filename);

        photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
    }
    else
    {
        Debug.LogError("Unable to start photo mode!");
    }
}

Depois de capturar a foto para o disco, saia do modo fotográfico e, em seguida, limpe os seus objetos

void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
{
    if (result.success)
    {
        Debug.Log("Saved Photo to disk!");
        photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
    }
    else
    {
        Debug.Log("Failed to save Photo to disk");
    }
}

Capture uma foto para uma Texture2D com localização

Ao capturar dados para uma Texture2D, o processo é semelhante à captura ao disco.

Siga o processo de configuração acima.

In OnPhotoModeStarted, capture uma moldura para a memória.

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

Em seguida, aplicará o seu resultado a uma textura e utilizará o código comum de limpeza acima.

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

Câmera localização

Para colocar esta textura na cena e exibi-la utilizando as matrizes de câmara locatáveis, adicione o seguinte código ao OnCapturedPhotoToMemory na verificação:

if (photoCaptureFrame.hasLocationData)
{
    photoCaptureFrame.TryGetCameraToWorldMatrix(out Matrix4x4 cameraToWorldMatrix);

    Vector3 position = cameraToWorldMatrix.GetColumn(3) - cameraToWorldMatrix.GetColumn(2);
    Quaternion rotation = Quaternion.LookRotation(-cameraToWorldMatrix.GetColumn(2), cameraToWorldMatrix.GetColumn(1));

    photoCaptureFrame.TryGetProjectionMatrix(Camera.main.nearClipPlane, Camera.main.farClipPlane, out Matrix4x4 projectionMatrix);
}

A unidade forneceu um código de amostra para aplicar a matriz de projeção a um shader específico nos seus fóruns.

Capture uma foto e interaja com os bytes crus

Para interagir com os bytes crus de um quadro de memória, siga os mesmos passos de configuração acima e OnPhotoModeStarted como na captura de uma foto para uma Texture2D. A diferença está no OnCapturedPhotoToMemory onde pode obter os bytes crus e interagir com eles.

Neste exemplo, irá criar uma Lista para ser processado ou aplicado a uma textura através do SetPixels()

void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
    if (result.success)
    {
        List<byte> imageBufferList = new List<byte>();
        // Copy the raw IMFMediaBuffer data into our empty byte list.
        photoCaptureFrame.CopyRawImageDataIntoBuffer(imageBufferList);

        // In this example, we captured the image using the BGRA32 format.
        // So our stride will be 4 since we have a byte for each rgba channel.
        // The raw image data will also be flipped so we access our pixel data
        // in the reverse order.
        int stride = 4;
        float denominator = 1.0f / 255.0f;
        List<Color> colorArray = new List<Color>();
        for (int i = imageBufferList.Count - 1; i >= 0; i -= stride)
        {
            float a = (int)(imageBufferList[i - 0]) * denominator;
            float r = (int)(imageBufferList[i - 1]) * denominator;
            float g = (int)(imageBufferList[i - 2]) * denominator;
            float b = (int)(imageBufferList[i - 3]) * denominator;

            colorArray.Add(new Color(r, g, b, a));
        }
        // Now we could do something with the array such as texture.SetPixels() or run image processing on the list
    }
    photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}

Captura de vídeo

Espaço de nome (antes da Unidade 2019):UnityEngine.XR.WSA.WebCam
Espaço de nome (Unidade 2019 e mais tarde):UnityEngine.Windows. WebCam
Tipo:VideoCapture

O VideoCapture funciona da mesma forma que o PhotoCapture. As duas únicas diferenças são que deve especificar um valor Frames por Segundo (FPS) e só pode guardar diretamente para o disco como um ficheiro .mp4. Os passos para utilizar o VideoCapture são os seguintes:

  1. Criar um objeto VideoCapture
  2. Crie um objeto CameraParameters com as definições desejada
  3. Iniciar modo de vídeo via StartVideoModeAsync
  4. Comece a gravar vídeo
  5. Pare de gravar vídeo
  6. Pare o modo de vídeo e limpe os recursos

Comece por criar o nosso objeto VideoCaptureVideoCapture m_VideoCapture = nulo;

void Start ()
{
    VideoCapture.CreateAsync(false, OnVideoCaptureCreated);
}

Em seguida, configurar os parâmetros que vai querer para a gravação e arranque.

void OnVideoCaptureCreated(VideoCapture videoCapture)
{
    if (videoCapture != null)
    {
        m_VideoCapture = videoCapture;

        Resolution cameraResolution = VideoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
        float cameraFramerate = VideoCapture.GetSupportedFrameRatesForResolution(cameraResolution).OrderByDescending((fps) => fps).First();

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

        m_VideoCapture.StartVideoModeAsync(cameraParameters,
                                            VideoCapture.AudioState.None,
                                            OnStartedVideoCaptureMode);
    }
    else
    {
        Debug.LogError("Failed to create VideoCapture Instance!");
    }
}

Uma vez iniciado, inicie a gravação

void OnStartedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
    if (result.success)
    {
        string filename = string.Format("MyVideo_{0}.mp4", Time.time);
        string filepath = System.IO.Path.Combine(Application.persistentDataPath, filename);

        m_VideoCapture.StartRecordingAsync(filepath, OnStartedRecordingVideo);
    }
}

Após o início da gravação, pode atualizar a sua UI ou comportamentos para permitir a paragem. Aqui basta fazer o registo.

void OnStartedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
    Debug.Log("Started Recording Video!");
    // We will stop the video from recording via other input such as a timer or a tap, etc.
}

Num ponto posterior, deverá parar a gravação utilizando um temporizador ou entrada do utilizador, por exemplo.

// The user has indicated to stop recording
void StopRecordingVideo()
{
    m_VideoCapture.StopRecordingAsync(OnStoppedRecordingVideo);
}

Uma vez interrompida a gravação, pare o modo de vídeo e limpe os seus recursos.

void OnStoppedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
    Debug.Log("Stopped Recording Video!");
    m_VideoCapture.StopVideoModeAsync(OnStoppedVideoCaptureMode);
}

void OnStoppedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
    m_VideoCapture.Dispose();
    m_VideoCapture = null;
}

Resolução de problemas

  • Não existem resoluções
    • Certifique-se de que a capacidade webCam está especificada no seu projeto.

Próximo checkpoint de desenvolvimento

Se está a seguir a jornada de controlo de desenvolvimento da Unidade que estabelecemos, está no meio de explorar as capacidades da plataforma de Realidade Mista e APIs. A partir daqui, pode continuar para o próximo tópico:

Ou salte diretamente para a implementação da sua aplicação num dispositivo ou emulador:

Pode sempre voltar aos postos de controlo de desenvolvimento da Unidade a qualquer momento.

Ver também