Combinando OpenCV con Xlib

Este post va de programación. La mayoría de veces que hacemos programas que tienen que tratar con imágenes se da el caso de que el programa trabajará en un entorno de escritorio con su gestor de ventanas y con sus librerías para hacer interfaces gráficas. Pero como he dicho, eso será la mayoría de veces, que no todas.

Algunas veces nos encontraremos con que como mucho podremos hacer funcionar el servidor gráfico X, pero nada de GTK, Qt, KDE, XFCE, Enlightenment o pijadas por el estilo. Esto nos puede suceder cuando estamos programando algo para una máquina con pocos recursos y aun así tenemos que mostrar alguna que otra imagen por pantalla.

Una de las librerías más eficientes que existen para tratar imágenes es OpenCV . OpenCV provee (a parte de las rutinas de tratamiento de imagen) rutinas que permiten mostrar por pantalla las imágenes, en particular, permite mostrarlas en ventanas. El problema de estas rutinas es que dependen o bien de GTK o bien del entorno gráfico de Windows o bien de las librerías Carbon de Mac OS X . Por ello mostraré como transformar un objeto imagen de OpenCV en uno de las librerías Xlib para poder mostrar por pantalla las imágenes incluso en los entornos más austeros.

OpenCV maneja las imágenes a través de punteros a estructuras del tipo IplImage, Xlib las maneja a través de punteros a estructuras del tipo XImage. El siguiente código es una función que acepta como argumento un puntero a una estructura del tipo IplImage y devuelve un puntero a una estructura del tipo XImage (a la que luego se le tendrá que aplicar la función XDestroyImage una vez que hayamos acabado de usarla para liberar recursos). Me dejo de rollos y os cuelgo el código:

Ximage* OCVtoX(Display *display, IplImage* img, int depth) {
    char   *buf_result;
    Ximage *img_result;
    uchar *ptr, *ptr2;
    uint n;

    buf_result = (char*)malloc(sizeof(char)*4*img->width*img->height);
    if(buf_result==0)
	return 0;

    img_result = XCreateImage(display, CopyFromParent, depth,
	ZPixmap, 0, buf_result, img->width, img->height, 32, 0);
    if(img_result==0) {
	free(buf_result);
	return 0;
    }

    // Normalmente sólo hay 3 canales, pero por si acaso hubiera 4
    n = img->nChannels;

    for(y=0; y < img->height; y++) {
	ptr  = (uchar*) (img->imageData + y*img->widthStep);
	ptr2 = (uchar*) (buf_result + y*4*img->width);
	for(x=0; x < img->width; x++) {
	    ptr2[4*x]=ptr[n*x];
	    ptr2[4*x+1]=ptr[n*x+1];
	    ptr2[4*x+2]=ptr[n*x+2];
	}
    }

    return img_result;
}

Espero que a alguien le sirva... :p . (Por cierto, está licenciado bajo GPL 3.0 , xD.. aunque no lo vaya a utilizar nadie)

Números: 1

Vamos a ver que tiene de "especial" el número 1 (por perder un poco el tiempo):

  • Cualquier número multiplicado por él es igual a él mismo: a·1=a .
  • Su inverso es él mismo, o equivalentemente, cualquier número dividido entre él es él mismo: a/1 = a .
  • Cualquier número elevado a 1 es él mismo : a1=a .
  • Es el número de dimensiones de una recta .
  • Sea Φ un ángulo cualquiera, entonces 1 es igual a sin2(Φ)+cos2(Φ) .
  • Se conjetura (conjetura de Collatz) que si se aplican los siguientes pasos a un número natural, siempre se llegará al número 1:
  • Si se tiene un número par, entonces lo dividimos entre 2: 2·a ⟿ a .
  • Si se tiene un número impar, entonces lo multiplicamos por 3 y le sumamos 1: a ⟿ 3·a+1 .
  • Al resultado le volvemos a aplicar el mismo procedimiento, finalmente llegaremos al número 1!
  • Es uno de los 4 números que aparece en la "fórmula de Dios" (caso particular de la fórmula de Euler): eπi=-1 .
  • Todos los números naturales se pueden expresar como una suma finita de unos.
  • Es el único natural no divisible por ningún número primo.
  • Es el único número real x de la forma x=(x+1)(x-1) (la demostración es muy sencilla, pero entretenida también).
  • El conjunto más pequeño (el vacío) tiene 1 subconjunto.

Ale, ya me he cansado, si tenéis más ideas (y no os da pereza) podéis comentarlas :) .