Câmera de foto/vídeo no Unity
Habilitando o recurso de acesso à câmera
A funcionalidade "WebCam" deve ser declarada para que um aplicativo use a câmera.
- No Editor do Unity, vá para as configurações do player navegando até a página "Edit > Project Settings > Player"
- Selecione a guia "Windows Store"
- Na seção "Recursos de configurações > de publicação", verifique os recursos de WebCam e microfone
Apenas uma única operação pode ocorrer com a câmera por vez. Você pode verificar em UnityEngine.XR.WSA.WebCam.Mode
qual modo a câmera está atualmente no Unity 2018 e versões anteriores ou UnityEngine.Windows.WebCam.Mode
no Unity 2019 e versões posteriores. Os modos disponíveis são foto, vídeo ou nenhum.
Captura de fotos
Namespace (antes do Unity 2019): UnityEngine.XR.WSA.WebCam
Namespace (Unity 2019 e posterior): UnityEngine.Windows.WebCam
Tipo: PhotoCapture
O tipo PhotoCapture permite tirar fotografias com a Câmara de Vídeo Fotográfico. O padrão geral para usar o PhotoCapture para tirar uma foto é o seguinte:
- Criar um objeto PhotoCapture
- Crie um objeto CameraParameters com as configurações desejadas
- Inicie o modo de foto por meio de StartPhotoModeAsync
- Tire a foto que você quer
- (opcional) Interaja com essa imagem
- Pare o Modo Foto e limpe os recursos
Configuração comum para PhotoCapture
Para todos os três usos, comece com as mesmas três primeiras etapas acima
Comece criando um objeto PhotoCapture
private void Start()
{
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}
Em seguida, armazene seu objeto, defina 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, você também usará o mesmo código de limpeza apresentado aqui
void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
photoCaptureObject.Dispose();
photoCaptureObject = null;
}
Após essas etapas, você pode escolher qual tipo de foto capturar.
Capturar uma foto para um arquivo
A operação mais simples é capturar uma foto diretamente em um arquivo. A foto pode ser salva como JPG ou PNG.
Se você iniciou o modo de foto com sucesso, tire uma foto e armazene-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 de foto e limpe 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");
}
}
Capturar uma foto em um Texture2D com localização
Ao capturar dados em um Texture2D, o processo é semelhante à captura em disco.
Siga o processo de configuração acima.
Em OnPhotoModeStarted, capture um quadro na memória.
private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
if (result.success)
{
photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
}
else
{
Debug.LogError("Unable to start photo mode!");
}
}
Em seguida, você aplicará o resultado a uma textura e usará o código de limpeza comum 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 localizável
Para colocar essa textura na cena e exibi-la usando as matrizes de câmera localizáveis, adicione o seguinte código a OnCapturedPhotoToMemory na result.success
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);
}
O Unity forneceu um código de exemplo para aplicar a matriz de projeção a um sombreador específico em seus fóruns.
Capture uma foto e interaja com os bytes brutos
Para interagir com os bytes brutos de um quadro na memória, siga as mesmas etapas de configuração acima e OnPhotoModeStarted como na captura de uma foto em um Texture2D. A diferença está em OnCapturedPhotoToMemory , onde você pode obter os bytes brutos e interagir com eles.
Neste exemplo, você criará uma lista para ser processada ou aplicada a uma textura por meio de 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
Namespace (antes do Unity 2019): UnityEngine.XR.WSA.WebCam
Namespace (Unity 2019 e posterior): UnityEngine.Windows.WebCam
Tipo: VideoCapture
O VideoCapture funciona de forma semelhante ao PhotoCapture. As únicas duas diferenças são que você deve especificar um valor de quadros por segundo (FPS) e só pode salvar diretamente no disco como um arquivo .mp4. As etapas para usar o VideoCapture são as seguintes:
- Criar um objeto VideoCapture
- Crie um objeto CameraParameters com as configurações desejadas
- Inicie o modo de vídeo por meio de StartVideoModeAsync
- Comece a gravar vídeo
- Pare de gravar vídeo
- Pare o modo de vídeo e limpe os recursos
Comece criando nosso objeto VideoCapture VideoCapture m_VideoCapture = null;
void Start ()
{
VideoCapture.CreateAsync(false, OnVideoCaptureCreated);
}
Em seguida, configure os parâmetros desejados para a gravação e comece.
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, comece 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, você pode atualizar sua interface do usuário ou comportamentos para habilitar a parada. Aqui você apenas registra.
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.
}
Posteriormente, você desejará interromper a gravação usando um cronômetro ou entrada do usuário, por exemplo.
// The user has indicated to stop recording
void StopRecordingVideo()
{
m_VideoCapture.StopRecordingAsync(OnStoppedRecordingVideo);
}
Depois que a gravação for interrompida, pare o modo de vídeo e limpe 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;
}
Solução de problemas
- Não há resoluções disponíveis
- Certifique-se de que o recurso WebCam esteja especificado em seu projeto.
Próximo ponto de verificação de desenvolvimento
Se você estiver seguindo a jornada de ponto de verificação de desenvolvimento do Unity que apresentamos, estará no meio da exploração dos recursos e APIs da plataforma Realidade Misturada. Deste ponto, você pode prosseguir para o próximo tópico:
Ou vá diretamente para a implantação de seu aplicativo em um dispositivo ou emulador:
Você sempre pode voltar para os pontos de verificação de desenvolvimento do Unity a qualquer momento.