miércoles, 30 de junio de 2010

Procesamiento de Video en Tiempo Real

Al fin otro post ... han pasado meses desde mi último post y hoy mientras revisada algunos apuntes de la universidad encontré un programa que hice en mis ratos libres acerca del procesamiento de video. Antes de escribir este pequeño código tenía un montón de dudas acerca del procesamiento de video. Y de eso trata este post, de dar solución a esas dudas que obviamente no son solo mías sino seguro de muchos novatos en programación. Bueno, luego de esta pequeña introducción empezemos a hablar acerca del procesamiento de video resolviendo las dudas que yo tenía.
Mi primera duda era: ¿Qué hace diferente al procesamiento de imágenes del procesamiento de video? ... Y esta duda me surgió porque yo tenía la implementación de algunos algoritmos de procesamiento de imágenes y pensaba que quizás podría aplicarlos en alguna cosa interesante. La respuesta a esta pregunta es que es casi lo mismo, es más, me animaría a decir que el procesamiento de video no es más que el procesamiento secuencial de imágenes dentro de un intervalo de tiempo.
Y es que para lograr procesar video solo basta acceder a sus frames e ir procesando imágen por imágen al mismo tiempo que es capturado para poder dar la sensación de movimiento y que es tiempo real.

First doubt has been solved!!

Mi segunda duda era: ¿Y qué herramientas puedo utilizar para poder procesar el video? ... Evidentemente hay muchas, pero yo personalmente prefiero Java que son su framework JMF(Java Media Framework) (que evidentemente no es la gran cosa, así que no pidamos maravillas) nos provee la API necesaria para poder acceder a los dispositivos de captura de video y también manipular los datos de un achivo multimedia.

Tercera duda: Bien, ya instalé el Java Media Framework, ahora ¿Cómo instancio un dispositivo de captura de video? ... Bueno, como siempre digo: Un poco de líneas de código dice más que mil papers

package view;

import java.awt.BorderLayout;
import javax.media.CaptureDeviceInfo;
import javax.media.CaptureDeviceManager;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.Player;
import javax.media.Processor;
import javax.swing.JFrame;

/**
*
* @author Rolando
*/
public class InstanciarCamara extends JFrame {

private static Player player;
private MediaLocator localizador;
private Processor p;
private CaptureDeviceInfo dispositivo = null;
private static String source = "vfw:Microsoft WDM Image Capture (Win32):0";

public InstanciarCamara() {
setLayout(new BorderLayout());
setSize(500, 400);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Demo Cámara Web");
player = null;
localizador = null;
dispositivo = CaptureDeviceManager.getDevice(source);
localizador = dispositivo.getLocator();
iniciarCaptura();
}

private void iniciarCaptura() {
try {
player = Manager.createRealizedPlayer(localizador);
player.start();
if (player.getVisualComponent() != null) {
add(player.getVisualComponent(), BorderLayout.CENTER);
}
} catch (Exception e) {
System.err.println(e.toString());
}
}

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
InstanciarCamara.setDefaultLookAndFeelDecorated(true);
InstanciarCamara camara = new InstanciarCamara();
camara.setVisible(true);
}

}


Con eso ya podemos acceder a una cámara web por ejemplo.

Cuarta duda: Bien, ya puedo acceder a un dispositivo de captura, pero ¿Cómo accedo a los frames para poder procesarlos? Y es aquí donde el java media framework otra vez, gracias a su API, nos provee unos métodos que nos ayudarán a realizar esta tarea. A ver, veamos estas palabras reflejadas en otro poco de código.

Primero necesitaremos un panel para poder cargar la imágen procesada. Este panel solo reescribirá el método paint. A continuación el código.

/*
* Lienzo.java
*
* Created on 14/05/2009, 02:11:36 PM
*/

package com.test;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

/**
*
* @author Rolando
*/
public class Lienzo extends javax.swing.JPanel {

private BufferedImage imagen;

public Lienzo() {
imagen = null;
}

public void setImage(BufferedImage imagen) {
this.imagen = imagen;
repaint();
}         

@Override
public void paint( Graphics g ) {
super.paint( g );
if( imagen != null ) {
g.drawImage(imagen, 0, 0, getWidth(), getHeight(), this);
g.setColor(Color.BLACK);
g.drawString("http://rolandopalermo.blogspot.com", 10, 20);
}
}                 

}


Y ahora para ver como se capturan los frames del video proveniente de una cámara web les dejo un pequeño proyecto de netbeans.

Photobucket

Espero les sea de utilidad y cualquier pregunta, no duden en consultarme.