viernes, 25 de enero de 2013

Realidad Aumentada - Parte I - Captura de Cámara y Video

El elemento que tienen en común las aplicaciones de realidad aumentada es que son realizadas sobre la captura de video en vivo. Veremos algunos conceptos básicos sobre como usar la cámara, ejemplos de captura de video y luego analizaremos el video frame por frame.

Primero es importante chequear la disponibilidad del sensor o del componente de hardware. Se puede detectar que cámara esta disponible en tu dispositivo usando la clase UIImagePickerController. Existe un método llamado isSourceTypeAvailable que podemos usar para determinar si la cámara que queremos usar esta disponible.

El siguiente código nos muestra un alerta. Lo que hacemos es chequear la existencia de UIImagePickerControllerSourceTypeCamera para saber si esta disponible la cámara. Luego chequeamos si la cámara que esta disponible es la frontal con el parámetro UIImagePickerControllerCameraDeviceFront. Estos ejemplos se deben ejecutar en un dispositivo real ya que el simulador no soporta cámara o video.

BOOL cameraAvailable = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
BOOL frontCameraAvailable = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerCameraDeviceFront];

if (cameraAvailable) {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Camara"
                                                    message:@"Camara Disponible" delegate:self
                                          cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
    [alert show];
    [alert release]; 
} else {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Camera" message:@"La Camara no esta disponible" delegate:self cancelButtonTitle:@"OK"
                                          otherButtonTitles:nil, nil];
                              
                              [alert show];
                              [alert release]; 
}
                              
if (frontCameraAvailable) {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Camara" message:@"Camara Frontal Disponible"
                                                   delegate:self cancelButtonTitle:@"OK"
                                          otherButtonTitles:nil, nil]; 

          [alert show];
          [alert release];
    } else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Camara"                                                 message:@"Front Camera NOT Available"
                              [alert show];
                              [alert release]; }
                                                       delegate:self cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil, nil];

    } 
Realizar una captura de una foto en iOS no es complicado. La clase UIImagePickerController tiene métodos para sacar una foto, acceder a la cámara e incluso hacer un preview de las fotos.

Creamos un nuevo proyecto del tipo Tabbed Application como se muestra en la siguiente captura. Llamemoslo AugmentedRealityCamera.



El storyboard deberia verse como la siguiente imagen:



Es conveniente que comencemos el proyecto desde cero, para eso borramos FirstViewController.h, FirstViewController.m, SecondViewController.h, y SecondViewController.m. También borramos los archivos .png asociados a la vista y las interfaces de FirstViewController y SecondViewController en los 2 storyboards (el del ipad y el del iphone). Lo único que debe quedar en el storyboard es el tabBar y en el proyecto deben quedar solo los dos storyboards y el AppDelegate.

Ya teniendo limpio todo el proyecto comenzamos tomando una foto y guardandola en la libreria del dispositivo. Entonces agregamos un view controller para este ejemplo y lo unimos a uno de los tab en el tab bar controller.

Para esto hacemos click derecho sobre la carpeta del proyecto y elegimos New File desde el menú de contexto. Elegimos la subclase UIViewController como template para este nuevo archivo.

Hacemos click en Next. Nos aseguramos que seleccionamos las opciones que aparecen en la siguiente captura.

Seleccionamos un View Controller desde la libreria de objetos y lo arrastramos a la interface. Hacemos click en el nuevo View Controller y cambiamos en el identity inspector la clase por la que creamos recién PhotoViewController. El resultado de estos 3 pasos se muestra en la siguiente figura:


Repetimos este proceso en el storyboard del ipad si queremos que también funcione en el mismo. Luego arrastramos un UIButton al PhotoViewController en el interface builder. Nos aseguramos que el editor asistente este activo y este presente el PhotoViewController.h, lo que hacemos es ctrl+arrastrar desde el botón hasta el archivo .h para crear la acción con este oulet.

A la acción la llamamos loadPhotoPicker. Si queremos que la aplicación sea universal debemos hacer este paso nuevamente para el ipad.
Ahora vamos a completar el método loadPhotoPicker:
 
- (IBAction)loadPhotoPicker:(id)sender {
 UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
 // uncomment for front camera
 // imagePicker.cameraDevice = UIImagePickerControllerCameraDeviceFront; 
imagePicker.delegate = self;
 imagePicker.allowsEditing = NO;
 [self presentModalViewController:imagePicker animated:YES];
 }


Este método crea una instancia de la clase UIImagePickerController. Lo que hace esta clase es abrir la interface de la cámara que utilizamos en iOS. Seteamos para utilizar la cámara trasera. Si queremos utilizar la delantera primero deberia mos ver si esta disponible. Luego seteamos el delegate to self, deshabilitamos la edición del image picker y presentamos el UIImagePickerController como modal. Si lo ejecutamos se mostrara la cámara pero no se guardara nada. Métodos para guardar una imagen:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
    UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}


- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
    UIAlertView *alert; if (error) {
    alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                       message:@"No se puede guardar la imagen en el album de fotos." 
                                      delegate:self cancelButtonTitle:@"Ok" 
                             otherButtonTitles:nil];
    } else {
        alert = [[UIAlertView alloc] initWithTitle:@"Success"
                                           message:@"Imagen Guardada." 
                                          delegate:self 
                                 cancelButtonTitle:@"Ok"
                                 otherButtonTitles:nil];
    }
    [alert show];
    [self dismissModalViewControllerAnimated:YES];
}           
El primer método es un método delegado de la clase UIImagePickerController que se dispara cuando se selecciona una imagen desde el controlador. Hacemos un alloc de este objeto para la imagen y lo enviamos al segundo método que se motro anteriormente. El segundo método que se establece como el selector que se llama después de guardar el archivo chequea se existe algún error y muestra el mensaje de alerta. Recordemos que solo podemos testear este ejemplo en un dispositivo real ya que el simulador no nos permite tomar fotos.

Código de esta primera parte: Realidad Aumentada - Parte 1

1 comentario:

Anónimo dijo...

Buen artículo. Una pregunta rápida:
¿Es posible incorporar en la foto a nivel de fichero o de imagen las coordenadas del dispositivo?

Gracias!