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.

39 comentarios:

Erick Arroyo dijo...

Exelente trabajao, te quisiera molestar que me ayudes con un cliente servidor, que el servidor capture el video y la envie a los clientes. Te agradeceria mucho.

Rolando dijo...

Claro amigo, lo que tienes que utilizar es Java Media Framework y el protocolo RTP Real-time Transport Protocol (Protocolo de Transporte de Tiempo real). Con eso podrás hacer lo que quieres, que supongo es un programa para videoconferencia o videovigilancia.

Erick Arroyo dijo...

Gracias por responder, la verdad es un proyecto de la Universidad, es un Aula Virtual y lo unico que me queda es compartir video con los alumnos, he conseguigo muchos codigos de java con JMF pero ninguno que me guie de como transmitir de cliente a servidor. Te agradeceria tu ayuda.

Rolando dijo...

Claro amigo, pero has buscado ejemplos sobre RTP? http://java.sys-con.com/node/45832

Erick Arroyo dijo...

Asi es, ya habia visitado el link que colocaste pero es para un servicio web, el proyecto lo estoy realisando en netbeans para una aplicacion de escritorio asi como lo que programaste. Lo que necesito es exactamente igual a esto http://www.youtube.com/watch?v=thvxozuYy8w&feature=related

Rolando dijo...

Nunca lo había hecho así pero es cuestión de crear una clase Imagen, serializarla y enviarla como cualquier objeto.

Erick Arroyo dijo...

Ok, voy a seguir buscando, de todas formas gracias por tu ayuda. Y que buen Blog.

Rolando dijo...

Esto te puede servir http://rolandopalermo.blogspot.com/2010/08/transmision-de-video-usando-sockets-en.html

Erick Arroyo dijo...

Uffffffff, me salvaste la vida, muchas gracias por todo, te deje un comentario en el link que adjuntaste. Muuuuuuuuuuuuuuuuchas gracias.

Anónimo dijo...

amigo que buena ayuda, sucede que al correr el programa en netbeans me arroja el siguiente error

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException

at com.blogspot.rolandopalermo.Acceder2Frames.(Acceder2Frames.java:53)

com.blogspot.rolandopalermo.Acceder2Frames$4.run(Acceder2Frames.java:185)

java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)

realmente es muy importante para mi es la base de una aplicacion que necesito desarrollar te agradesco inmensamente de antemano la ayuda que me puedas brindar. junior230481@gmail.com

Anónimo dijo...

¿como se puede hacer para que el video se vea binarizado?
Es que yo consigo coger una foto de la camara y binarizarla, pero no que ver un video en tiempo real.
Muchas gracias de antemano

alvaro dijo...

yo tambien estaria interesado en saber el método para mostrar el video binarizado, que he estado buscando por todos lados y no encuentro nada.

Rolando dijo...

Buen día a todos. Se refieren a que se vea así como en el video que muestro?

alvaro dijo...

si, es que estoy intentando hacer un programa que calcule una serie de parametros sobre la imagen binarizada, y necesito que la imagen se muestre en tiempo real, y poder contar por ejemplo los puntos negros que salen en la imagen en cada momento.
Pero de momento solo con que me muestres como poner la imagen binarizada creo que seria suficiente, ya lo otro lo haria con bucles for.

Rolando dijo...

Pues eso se logra con un timer amigo. Si tienes tu algoritmo para binarizar una imágen en java, ese mismo puedes usar dentro del evento del timer. Así cada 1 milisegundo tienes la imágen binarizada.
Saludos.

alvaro dijo...

tengo un bucle do while, que me hace todo eso, pero solo me repinta la imagen cuando termina de realizar todos los bucles, y solo pinta una imagen.

Rolando dijo...

Es que eso no se hace con un bucle do while, sino con un timer.

alvaro dijo...

ok, pues ese era mi fallo, muchas gracias, voy a probar a ver si me aclaro y te cuento.

alvaro dijo...

Ya lo tengo funcionando, muchisimas gracias por la atención prestada y por la ayuda, y lo siento si mis preguntas has sido demasiado tontas.
Da gusto tratar con gente como tú.

Anónimo dijo...

hola tengo un proble no quere correr el proyecto que descarge del procesamiento de imagenes me sale estos errores

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at com.blogspot.rolandopalermo.Acceder2Frames.(Acceder2Frames.java:53)
at com.blogspot.rolandopalermo.Acceder2Frames$4.run(Acceder2Frames.java:185)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)

podes ayudarme soy un novato en netbean my correo es vsblackmetal@yahoo.es porfa

Rolando dijo...

Intenta esto:
1. Usa el JMF Studio para detectar dispositivos de captura de video.
2. Cambia "vfw:Microsoft WDM Image Capture (Win32):0" por "vfw://0"

Anónimo dijo...

te amo mi amorrr!!!! :$ perdona esto no tiene nada q ver con la pagina,pero queria q lo sepas y q nunca se t olvide ni un segundo vale??? t adorooo mumi!

cesar dijo...

hola,

Excelente trabajo! quisiera saber si con JMF se puede hacer lo siguiente:

necesito capturar video desde un dispositivo, el video (conjunto de frames) necesito poder meterlos en una matriz de n x m (resolucion de imagen), y a cada matriz (foto o frame) poder analizar el color de cada pixel.

Se traduce a lo siguiente, imagina estoy capturando un video de cualquier cosa, si me posiciono con el cursor sobrl alguna region del video mientras lo reproduzco en tiempo real, necesito que me diga que color tiene el pixel que en el que estoy posicionado en todo instante de tiempo.

Sería genial si me puedes ayudar con esto.

de antemano muchas gracias

atte César.

Matias dijo...

Hola muy bueno el blog, estoy trabajando en un proyecto y me interesaria saber si es posible capturar el video en tiempo real desde una camara digital NIKON conectada por usb a la pc...

DESDE YA MUCHAS GRACIAS.

Rolando dijo...

Si es posible amigo.

Matias dijo...

Muchas gracias por tu respuesta! La duda que tengo es que cargando la libreria javax.media me dice que es deprecated, hay alguna nueva que la sustituya?

y otra duda que tengo es comoseteo para que capture el video desde la camara que esta conectada por usb, por que para una camara web comun ya lo tengo echo (para las web cam de un notebook por ejemplo), pero me complica el tema del usb...

Desde ya muchas gracias!

Matias dijo...

Rolando:

Quisiera pedirte tu ayuda para que me des una pista de como capturar imagen desde una camara digital nikon p300 a la pc, puedo capturar en un programa java la imagen tomada desde una web cam, pero no desde la nikon.

Agredeceria muchisimo tu ayuda!

gerson123 dijo...

ayudaaaaaaaaaaaaa!!!!!
cuando quiero cargar el video de mi webcam en un panel me genera el sigueinte error noc si sea por los thread que estoi utilizando en el chat de java
xq kiero implementarlo para hacer un video chat alguna ayuda me serviria de antemano gracias!!!!!!
aki esta el error que me genera
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at ClienteChat.jmfVideo.Componente(jmfVideo.java:31)
at ClienteChat.Clientes.jButton1ActionPerformed(Clientes.java:340)
at ClienteChat.Clientes.access$300(Clientes.java:27)
at ClienteChat.Clientes$5.actionPerformed(Clientes.java:200)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6289)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
at java.awt.Component.processEvent(Component.java:6054)
at java.awt.Container.processEvent(Container.java:2041)
at java.awt.Component.dispatchEventImpl(Component.java:4652)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Component.dispatchEvent(Component.java:4482)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4577)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
at java.awt.Container.dispatchEventImpl(Container.java:2085)
at java.awt.Window.dispatchEventImpl(Window.java:2478)
at java.awt.Component.dispatchEvent(Component.java:4482)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:644)
at java.awt.EventQueue.access$000(EventQueue.java:85)
at java.awt.EventQueue$1.run(EventQueue.java:603)
at java.awt.EventQueue$1.run(EventQueue.java:601)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98)
at java.awt.EventQueue$2.run(EventQueue.java:617)
at java.awt.EventQueue$2.run(EventQueue.java:615)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:614)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

J-D dijo...

hey q ondas esta bueno el post pero quiero saber como hacer para que corra en windows7....agradeceria tu pronta respuesta

Anónimo dijo...

hola rolando está muy bueno el post tengo que hacer un procesamiento de imagenes a unos microorganismos para mi estudio me gustaria saber si tienes algoritmos computacionales para ver como extraigo caracteriaticas de las imagenes... pleaseeeee!!!!!

Anónimo dijo...

primero que todo lo felicito por el post. nos ha sido de mucha ayuda.
y como estoy nuevo en el esto de la programacion. como puedo hacer que este codigo que coloco pueda detectar el color rojo cuando se lo pase por la camara.

de antemano muchas gracias

Anónimo dijo...

¿Como guardo el video en mi disco duro?

danny alexander osorio bermudez dijo...

Hola Rolando, saludos desde Cartagena-Colombia, he descargado el proyecto para probar pero me salen unas EXEPTION cuando ejecuto y es la siguiente...
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at com.blogspot.rolandopalermo.Acceder2Frames.(Acceder2Frames.java:55)
at com.blogspot.rolandopalermo.Acceder2Frames$4.run(Acceder2Frames.java:187)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:701)
at java.awt.EventQueue.access$000(EventQueue.java:102)
at java.awt.EventQueue$3.run(EventQueue.java:662)
at java.awt.EventQueue$3.run(EventQueue.java:660)

Por otra parte ya ejecute el JMStudio y esta todo bien con la cámara, después hice lo que tu sugieres de cambiar "vfw:Microsoft WDM Image Capture (Win32):0" por "vfw://0" pero nada...
Agradezco tu ayuda y estaré atento a tu respuesta...
Gracias!

Unknown dijo...

Amigo disculpa tengo este error y ya e mirado bastante tu codigo pero no consigo solucionarlo me podrias ayudar

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at com.blogspot.rolandopalermo.Acceder2Frames.(Acceder2Frames.java:55)
at com.blogspot.rolandopalermo.Acceder2Frames$4.run(Acceder2Frames.java:187)

gracias de ante mano

Unknown dijo...

Buenas noches:

amigos segui este post detalladamente y mire que muchos han tenido un error que se a vuelto viral y la verdad la solucion es muy facil.

solo tiene que ir en netbeans a la Liberia del proyecto e importar la librería jmf.jar y listo problema resuelto...!

Espero y se que les servirá a muchos...!

Jose Hernandez dijo...

Hola que tal bueno tu aterial pero tendras videos tutoriales para lo del acceso a las camaras es que deseo hacer un software de vigilancia y control de acceso me podrias apoyar saludos.

Anónimo dijo...

hola Rolando soy nuevo en esto y queria saber si podrias ayudarme me aparece el siguiente error
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at com.blogspot.rolandopalermo.Acceder2Frames.(Acceder2Frames.java:53)
at com.blogspot.rolandopalermo.Acceder2Frames$4.run(Acceder2Frames.java:185)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
at java.awt.EventQueue.access$400(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:697)
at java.awt.EventQueue$3.run(EventQueue.java:691)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
espero puedas ayduarme saludos.

Renato Avilés Santamaría dijo...

oye amigo necesito que me ayudaras sobre como poder hacer que en una videoconferencia la imagen del profesor no interfiera en la proyección que se esta enfocando es decir una de las maneras en que (tal vez) se pueda llevar a cabo. En la computadora receptora, guarde la imagen sin interferencia, y cuando detecte que hay una “interferencia de profesor”, conmute y despliegue sucesivamente una y otra imagen, esto nos dará el efecto de transparentar a la obstrucción y semi-removerla. Regrese a la imagen nueva cuando la obstrucción cese.

Anónimo dijo...

Hola, WVC80N, sorprendente equipo, le acabo de descubrir visión nocturna ajustándole los codecs, bueno los parámetros de los codecs, no es gran cosa pero consigue tonos blancos de tonos a un 80 % o 90 % oscuros en photoshop x ejemplo. La seguridad es excelente tiene audio, compatible con gran cantidad de equipos con navegación rtsp, alarma y acceso multiusuario. Diferenciación espacial hace saltar una alarma con movimiento en un recuadro, la wifi necesita ampliar sus configuraciones al igual que muchos teléfonos móviles pero va. Graba en dispositivos remotos, configurable, etc, reset, luz azul: de cámara azul, modos de luz azul, etc. Supongo que no tardaran en hacer otro firmware con control por aplicacion o un modelo fisheye nuevo, aplicativos dns, twitter, ...

Publicar un comentario