[Revista Occam's Razor] Hacks de media tarde. WebCam 3D

15 views
Skip to first unread message

David Martínez

unread,
May 5, 2010, 7:21:17 AM5/5/10
to Occam's Razor Mail List
Hola!

Hace algún tiempo un buen amigo me envió una noticia sobre una webcam
3D. Hace algunos meses salió, finalmente, a la venta por un precio de
unos 80 euros (un poquito menos).

http://www.minoru3d.com/

En aquel momento (cuando la cámara se anunción) me pareció que quizás
fuera posible hacer algo similar utilizando el driver vloopback
desarrollado por la gente de "motion".

http://www.lavrsen.dk/twiki/bin/view/Motion/VideoFourLinuxLoopbackDevice

Bueno, pues en media tarde lo hicimos funcionar... adjunto una
captura :)... el efecto no es muy bueno, ya que las cámaras no están
bien alineadas... pero bueno, es un hack de media tarde :).

Mis cámaras cuestan menos de 20 euros cada una, si bien es cierto que no
son capaces de dar 800x600... pero por la mitad de precio obtenemos casi
lo mismo y un montón de diversión XDDDDD... además tenemos dos cámaras
para hacer otras cosas :)

Por alguna razón skype no es capaz de utilizar ni mi webcam ni el
dispositivo virtual. Así que buscando por ahí encontré wengo, que parece
básicamente lo mismo. Así que con wengo es posible hacer
videoconferencias 3D :)

http://www.wengophone.com/

Parece que el problema es con mis webcams, así que si alguno se anima a
probar esto y consegue que funcione con otros programas me encantaría
conocer los detalles.

Las instrucciones de este "hack" serian estas:

- Necesitáis dos fuentes de video configuradas como /dev/video0 y
/dev/video1.

- Creamos el dispositivo de video loopback. Le damos un offset de 2 para
que se salte video0 y video1.

$ sudo insmod ./vloopback.ko dev_offset=2

Para obtener el vloopback.ko, solo tenéis que recompilar el paquete que
podéis descargar desde la web de motion.

- Comprobamos que el dispositivo virtual ha sido creado con éxito

$ dmesg
[ 6203.683748] /mnt/data/work/learning/vloopback-1.1/vloopback.c:
Video4linux loopback driver v1.1
[ 6203.683808] /mnt/data/work/learning/vloopback-1.1/vloopback.c:
Loopback 0 registered, input: video2,output: video3

- Y lanzamos el programa stereo con una línea similar a esta:

$ ./stereo /dev/video0 /dev/video1 /dev/video2 320x240 rgb24

El programa simplemente inicializa las dos camaras (video0 y video1),
captura las imagenes , las procesa (genera el anaglifo) y las manda a la
pipe que crea vloopback (video2). Más abajo podéis ver el código.

A partir de este momento si le decimos a nuestros programas que utilicen
el dispositivo /dev/video3, obtendremos el video anaglifo. Por ejemplo,
con xawtv, solo tenemos que hacer:

$ xawtv -c /dev/video3

Así es como hemos obtenido la captura :)

El programa stereo es una version modificada del ejemplo invert.c que
viene con vloopback. Solo hay que hacer un par de modificaciones a la
función main, que quedaría talqueasín:

int main (int argc, char **argv)
{
int i, devin0, devin1, devout, error, size;
int width;
int height;
char *image_out, *image_new0, *image_new1;
char palette[10]={'\0'};

if (argc != 6) {
printf("Usage:\n\n");
printf("stereo input0 input1 output widthxheight rgb24|yuv420p\n\n");
printf("example: stereo /dev/video0 /dev/video1 /dev/video2 352x288
yuv420p\n\n");
exit(1);
}

sscanf(argv[4], "%dx%d", &width, &height);
sscanf(argv[5], "%s", palette);

if (!strcmp(palette,"rgb24")) fmt = VIDEO_PALETTE_RGB24;
else if (!strcmp(palette,"yuv420p")) fmt = VIDEO_PALETTE_YUV420P;
else fmt = VIDEO_PALETTE_RGB24;


image_out=malloc(width*height*3);

devin0=open (argv[1], O_RDWR);
if (devin0 < 0) {
printf("Failed to open input video device
[%s]\nError:[%s]\n",argv[1],strerror(errno));
exit(1);
}

devin1=open (argv[2], O_RDWR);
if (devin1 < 0) {
printf("Failed to open input video device
[%s]\nError:[%s]\n",argv[1],strerror(errno));
exit(1);
}


devout=open (argv[3], O_RDWR);
if (devout < 0) {
printf ("Failed to open output video device
[%s]\nError:[%s]\n",argv[3],strerror(errno));
exit(1);
}

image_new0=start_capture (devin0, width, height);
if (!image_new0) {
printf("Capture error \n Error[%s]\n",strerror(errno));
exit(1);
}

image_new1=start_capture (devin1, width, height);
if (!image_new0) {
printf("Capture error \n Error[%s]\n",strerror(errno));
exit(1);
}

start_pipe(devout, width, height);
signal(SIGTERM, sig_handler);

printf("Starting video stream.\n");

size = width * height * 3;
error = 0;
while ( (noexit) && (!error)){
error += (next_capture(devin0, image_new0, width, height) == NULL);
error += (next_capture(devin1, image_new1, width, height) == NULL);

for (i = 0; i < size; i += 3)
{
// WengoPhone
#if 0
image_out[i + 0] = image_new1[i + 0];
image_out[i + 1] = image_new0[i + 1];
image_out[i + 2] = image_new0[i + 2];
#else
image_out[i + 0] = image_new0[i + 0];
image_out[i + 1] = image_new0[i + 1];
image_out[i + 2] = image_new1[i + 2];
#endif
}

if (put_image(devout, image_out, width, height)==0)
exit(1);
}

printf("You bought vaporware!\nError[%s]\n",strerror(errno));
close (devin0);
close (devin1);
close (devout);
free(image_out);
exit(0);
}

El programa es muy sencillo y creo que no requiere mayor explicación,
salvo el if 0 en la parte en la que se genera el anaglifo. Esto es
porque, wengo y xawtv configuran los dispositivos de forma diferente...
aparentemente uno como RGB y otro BGR... no sé porque sucede esto... es
algo para entretenerse en el futuro próximo :).

Creo que puede resultaros interesante para aplicaciones en las que
proceséis video y no tengáis ganas de escribir un visor o el código para
grabar el video (para eso está por ejemplo xawtv)... o incluso para
encadenar procesados... no sé, parece que tiene muchas posibilidades.

Si se os ocurre algina idea no dudéis en comentarla en la lista.

Saludos

--
GNU/EDMA HomePage : http://www.gnu.org/software/edma
Personal Web Pages : http://papermint-designs.com/dmo
Blogs (dmartin/picoFlamingo) : http://community.papermint-designs.com
Revista Occam's Razor : http://webs.uvigo.es/occams-razor
camara-anaglifa-1.png
Reply all
Reply to author
Forward
0 new messages