Cámara de fotos y vídeo en Unity
Habilitación de la funcionalidad para el acceso a la cámara
La funcionalidad "WebCam" debe declararse para que una aplicación use la cámara.
- En el Editor de Unity, vaya a la configuración del reproductor; para ello, vaya a la página "Editar > Project Configuración > Player".
- Seleccione la pestaña "Windows Store".
- En la sección "Publishing Configuración > Capabilities" (Funcionalidades de Configuración publicación), compruebe las funcionalidades WebCamy Microphone.
Solo se puede realizar una sola operación con la cámara a la vez. Puede comprobar con qué modo está actualmente UnityEngine.XR.WSA.WebCam.Mode
la cámara en Unity 2018 UnityEngine.Windows.WebCam.Mode
y versiones anteriores o en Unity 2019 y versiones posteriores. Los modos disponibles son foto, vídeo o ninguno.
Captura de fotos
Espacio de nombres (antes de Unity 2019):UnityEngine.XR.WSA.WebCam
Espacio de nombres (Unity 2019 y versiones posteriores):UnityEngine.Windows. Webcam
Type:PhotoCapture
El tipo PhotoCapture permite tomar fotografías con la cámara photo video. El patrón general para usar PhotoCapture para tomar una foto es el siguiente:
- Creación de un objeto PhotoCapture
- Cree un objeto CameraParameters con la configuración que desee.
- Iniciar el modo foto a través de StartPhotoModeAsync
- Tomar la foto que quiera
- (opcional) Interacción con esa imagen
- Detener el modo foto y limpiar los recursos
Configuración común de PhotoCapture
Para los tres usos, comience con los mismos tres primeros pasos anteriores.
Para empezar, cree un objeto PhotoCapture .
private void Start()
{
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}
A continuación, almacene el objeto, establezca los parámetros e inicie el 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);
}
Al final, también usará el mismo código de limpieza que se presenta aquí.
void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
photoCaptureObject.Dispose();
photoCaptureObject = null;
}
Después de estos pasos, puede elegir qué tipo de foto se va a capturar.
Capturar una foto a un archivo
La operación más sencilla es capturar una foto directamente en un archivo. La foto se puede guardar como JPG o PNG.
Si ha iniciado correctamente el modo de foto, tome una foto y guárdala en el 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!");
}
}
Después de capturar la foto en el disco, salga del modo de foto y, a continuación, limpie los 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");
}
}
Captura de una foto en un objeto Texture2D con ubicación
Al capturar datos en texture2D, el proceso es similar a la captura en el disco.
Siga el proceso de instalación anterior.
En OnPhotoModeStarted, capture un fotograma en la memoria.
private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
if (result.success)
{
photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
}
else
{
Debug.LogError("Unable to start photo mode!");
}
}
Después, aplicará el resultado a una textura y usará el código de limpieza común anterior.
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ámara localizable
Para colocar esta textura en la escena y mostrarla mediante las matrices de cámara localizables, agregue el código siguiente a OnCapturedPhotoToMemory en la result.success
comprobación:
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);
}
Unity ha proporcionado código de ejemplo para aplicar la matriz de proyección a un sombreador específico en sus foros.
Captura de una foto e interacción con los bytes sin procesar
Para interactuar con los bytes sin procesar de un marco en memoria, siga los mismos pasos de configuración anteriores y OnPhotoModeStarted como en la captura de una foto en texture2D. La diferencia está en OnCapturedPhotoToMemory , donde puede obtener los bytes sin procesar e interactuar con ellos.
En este ejemplo, creará una lista para procesarla o aplicarla a una textura a través 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
Espacio de nombres (antes de Unity 2019):UnityEngine.XR.WSA.WebCam
Espacio de nombres (Unity 2019 y versiones posteriores):UnityEngine.Windows. Webcam
Type:VideoCapture
VideoCapture funciona de forma similar a PhotoCapture. Las únicas dos diferencias son que debe especificar un valor Fotogramas por segundo (FPS) y solo puede guardar directamente en el disco como un archivo .mp4 segundo. Los pasos para usar VideoCapture son los siguientes:
- Creación de un objeto VideoCapture
- Cree un objeto CameraParameters con la configuración que desee.
- Iniciar el modo de vídeo a través de StartVideoModeAsync
- Inicio de la grabación de vídeo
- Detener grabación de vídeo
- Detener el modo de vídeo y limpiar los recursos
Empiece por crear el objeto VideoCaptureVideoCapture m_VideoCapture = null;
void Start ()
{
VideoCapture.CreateAsync(false, OnVideoCaptureCreated);
}
A continuación, configure los parámetros que deseará para la grabación e inicie.
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!");
}
}
Una vez iniciado, comience la grabación.
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);
}
}
Una vez iniciada la grabación, puede actualizar la interfaz de usuario o los comportamientos para habilitar la detención. Aquí solo tiene que iniciar sesión.
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.
}
En un momento posterior, querrá detener la grabación mediante un temporizador o una entrada de usuario, por ejemplo.
// The user has indicated to stop recording
void StopRecordingVideo()
{
m_VideoCapture.StopRecordingAsync(OnStoppedRecordingVideo);
}
Una vez detenida la grabación, detenga el modo de vídeo y limpie los 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;
}
Solución de problemas
- No hay soluciones disponibles
- Asegúrese de que la funcionalidad WebCam está especificada en el proyecto.
Siguiente punto de control de desarrollo
Si va a seguir el recorrido del punto de control de desarrollo de Unity que hemos diseñado, está a punto de explorar las API y las funcionalidades de la plataforma Mixed Reality desarrollo. Desde aquí, puede continuar con el siguiente tema:
O bien puede ir directamente a la implementación de la aplicación en un dispositivo o emulador:
Puede volver a los puntos de control de desarrollo de Unity en cualquier momento.