Hace unos momentos tuve este problema al instalar mi Kinect en Windows 7 de 64 bits.

El problema me surgió al querer compilar un proyecto en java desde Netbeans usando Kinect. Mi programa lo que hace es seguir a una persona y traza su esqueleto en la pantalla. Este proyecto lo obtuve desde los ejemplos de la pagina oficial de OpenNI y le hice ligeros cambios para personalizarlo. El problema fue que al querer compilarlo me apareció la leyenda:

 

“no OpenNI.jni in java.library.path”

 

Batalle un poco hasta encontrar la solución, se las dejo por si a alguien le es útil:

Primero, para instalar Kinect hay que descargar (de preferencia la versión inestable de 32 bits aunque tu máquina sea de 64)

1.-openni-win32-1.5.4.0-dev
2.-SensorKinect093-Bin-Win32-v5.1.2.1
3.-nite-win32-1.5.2.21-dev
4.-sensor-win32-5.1.2.1-redist

Donde el 1,3 y 4 se encuentran en la pagina oficial de OpenNI . Lo que me generaba el problema es que yo había descargado una versión anterior del SensorKinect (SensorKinect091-Bin-Win32-v5.1.0.25) y la que necesitaba era la listada arriba, entonces procedí a eliminar la version 091 y a instalar la 093, esto solucionó el problema. Ahora en mi proyecto de Java, solo importé la librería org.OpenNI.jar que está ubicada en C:\Program Files (x86)\OpenNI\Bin de mi máquina, esto dependerá del directorio que hayan elegido al instalar OpenNI.

OJO: La librería org.OpenNI.jar también aparece al instalar la versión 091 del sensorKinect, pero como que no hace referencia automática a una segunda librería que se necesita llamada OpenNI.jni que está en la carpeta C:\Program Files (x86)\OpenNI\Libs, no tengo idea de porqué.

 

Ya realicé un manual de cómo instalar Kinect en tu Windows 7 de 32 o 64 bits, el link acá.

 

Suerte.

Un día como cualquier otro se me antojó jugar el famosísimo tetris,  pero no cualquiera  si no la versión clásica de este. Así que me dispuse a buscarlo online, pero mi sorpresa fue grande cuando vi que no estaba la versión que yo quería.

 

Cuando era niña, mi padre solía jugar un tetris en el que te daban 3 corazones de vida, te daba entre 4 canciones a elegir y además tenía la opción en silencio. La pieza del tetris no podía ser bajada lentamente, al presionar el botón X la pieza bajaba de una sola vez.

 

Pues bien, todas las versiones que encontraba eran versiones desconocidas para mi. Indagando un poco, encontré que hay una versión de nintendo y otra versión de TENGEN, donde la segunda se volvió más popular por que su música era más pegajosa, ademas de que la pieza podía ser bajada lentamente. A mi me valió un cacahuate esto, yo quería la versión de nintendo, así que seguí buscando y por fin la encontré.

 

Se las dejo en este enlace. (Si no les aparece el juego, en la parte de abajo dice que está disponible la versión en java, den clic ahí y a mi sí me funcionó, obvio deben tener instalado java).

 

Además les dejo la otra versión de TENGEN que la verdad no está nada mal, pero yo quería recordar viejos tiempos. Aquí la versión TENGEN de tetris (es donde salen unos monitos bailando felices cada que pasas un nivel xD).

 

Enjoy gente. Nos vemos.

El día de hoy he acabado mi paquete de tocino FUD y he abierto el nuevo paquete Bafar. Estaba por cocinarlos y comerlos simplemente cuando se me ocurrió comparar las marcas. Así que puse mucha atención en la diferencia de las tiras de tocino. Anteriormente compré la marca BURR, y no se las recomiendo. Aquí les dejo las tres marcas y sus características según mi perspectiva:

BURR:

-Menos grasa en la tira de tocino
-Económico (de 23 a 25 pesos la bolsa de 250gr)
-Buena textura
-Sabe a cartón. Al freir la tirita comerla, el sabor es muy feo, no tiene las características propias del tocino, me decepcionó y aunque la tira tiene más carne que grasa, para mi, no vale la pena.

FUD:

-Mucha grasa en la tirita
-Sabor ahumado (a mi me ha gustado)
-Buena textura
-Económico (de 17 a 22 pesos el paquete de 250 gr, es que a veces está en oferta =D)
-El sabor es de un buen tocino ahumado, al morderlo sabe a grasita. El inconveniente que le vi a este tocino, es que si se frien varias tiritas juntas y no se dejan bien tostadas, el tocino sabe a pura grasa, entonces recomiendo que al freir, tiren un poco de la grasita que suelta y sigan con la cocción, de lo contrario las tiras se saturan de grasa.

Bafar:

-Grasa media en la tirita de tocino
-No ahumado
-Buena textura
-Tiras más delgadas que las otras dos (ojo, estas son más delgadas, no me refiero al ancho de la tira ni al largo, si no al grosor de la tirita de tocino)
-No tan económico (28 pesos la bolsa con 250 gr)
-Muy buen sabor, esta tira se parece al sabor de la anterior, solo que sin el sabor ahumado. Al cocer la tirita, las zonas de carne se vuelven más oscuras, pero igual saben delicioso.

En resumen, las tiras Bafar son las más buenas, seguidas por las FUD y al final las BURR que no saben a tocino (¬¬ que desilusión). Y aunque las tiras Bafar son más ricas, las tiras FUD no se quedan tan alejadas, y por el precio me parece que elegiría las FUD (28 pesos por el paquete de tocino es un robo, a veces hasta 32 pesos). Bueno, me hace falta probar el tocino KIR y el San Rafael. Proximamente estaré agregando esta info.

 

Bueno, espero les sirva y gracias por leer =D.

Antes de leer este post, puedes necesitar leer la introducción I aqui.

Notación asintótica

La notación asintótica, es una notación matemática formal que nos permite expresar las cotas bajo las que se encuentra el costo de cierto algoritmo, donde el costo puede ser en tiempo de ejecución, espacio requerido de almacenamiento, entre otros. Básicamente podemos acotar un algoritmo superiormente (O), inferiormente (Ω), y exactamente (Θ).

En el orden de (O)

Para explicar este concepto, imaginemos que tenemos una función cualquiera: t(n)=+2n+3. Supongamos que n es el tamaño de un ejemplar sobre el que queremos aplicar un algoritmo, y t(n) es la cantidad de  algún recurso que consume el algoritmo (tiempo, espacio…).

Antes de continuar, es necesario introducir el concepto del principio de invarianza, que dice que la razón de los tiempos de ejecución de dos implementaciones diferentes de un mismo algoritmo, siempre está acotada por encima y por debajo por constantes predeterminadas, donde las constantes pueden depender de las implementaciones de un algoritmo, pero no del tamaño del ejemplar en el que usaremos el algoritmo.

Ahora contemplemos otra función f(n)=. Podremos decir que t(n) está en el orden de f(n), si t(n) está acotada superiormente por un múltiplo real positivo de f(n) para todo n suficientemente grande.  Dicho matemáticamente, significa que existe una constante real y positiva y un umbral entero  tal que:

t(n) ≤ c f(n), siempre que n ≥         (0)

Ahora para entender esto, tomaremos las funciones definidas anteriormente, t(n)=+2n+3 y f(n)=. En t(n) aparece una , una n y una constante (3), ¿cuál de estas expresiones en más grande?.  Está claro que n≤ y que 1≤, siempre y cuando la n≥1 (si n=0, esto no se cumple), entonces, tomaremos el término más grande que es  y lo sustituimos en los demás términos más pequeños que son n y 1 ( 1 porque el último término de la función es 3, pero ocultamente ese 3 al ser una constante, está multiplicando al 1). Entonces tenemos que para n≥1:

t(n)=+2n+3          (1)

≤ +2+3           (2)

≤ 6                         (3)

≤ 6 f(n)                       (4)

En la Ec.(2) sustituimos el término más grande, entonces obviamente, el valor original de t(n), se vuelve menor que la nueva expresión. En la Ec.3 solo sumamos los términos y en Ec. 4, sustituimos  por f(n), que vale lo mismo. Entonces podemos observar que la constante de la que hablamos en la Ec.0, en éste ejemplo es c=6, y  =1. Dado que si existe una constante real positiva c, en un umbral entero , entonces podemos decir, que t(n), está en el orden de f(n).

Ahora, ya hemos dicho que t(n) puede representar cualquier unidad de costo, ya sean microsegundos, bits, años, etc. esto dependiendo de lo que estemos midiendo en nuestro algoritmo (después veremos la forma de obtener t(n)), pero por poner un ejemplo, diremos que nuestro algoritmo ejemplo tarda +2n+3 microsegundos en resolver un ejemplar de tamaño n, y ahora podemos decir que éste tiempo, está en orden de . Ahora bien, es válido decir que t(n) está en orden de f(n) para cualquier implementación de nuestro algoritmo, dado el principio de invarianza.

Para denotar matemáticamente “en el orden de”, se utiliza el simbolo “big O”, también conocida como “O grandota”. Por lo que es correcto expresar: t(n) ϵ O(f(n)), en nuestro ejemplo: (+2n+3) ϵ O().

Hoy hablaré de esta técnica de una manera sencilla, ya que en la mayoría de las explicaciones disponibles en la web, meten un montón de fórmulas y de explicaciones difíciles de entender.

 

Primeramente la definición

DTW  es un algoritmo para medir la similaridad entre dos secuencias, mismas que pueden variar en el tiempo o velocidad.

Para dejar más claro lo anterior, agrego la siguiente figura:

 

 

 

 

 

 

 

Supongamos que las curvas roja y negra representan dos señales de algún tipo, por decir un ejemplo, digamos que es sonido. Como puede observarse, ambas señales son la misma, con la diferencia de que una de ellas tiene mayor duración que la otra (supongamos que alguien dijo ‘hola’ lentamente y después dijo ‘hola’ con una velocidad normal, la señal será parecida pero con duración distinta), pero ambas presentan el mismo comportamiento: al inicio hay una curva grande hacia arriba, y después una curva grande hacia abajo, para finalizar con una pequeña curva hacia arriba al final.

Si tratamos de comparar estás dos señales con un algoritmo simple (comparando el 1er punto de la señal 1 con el 1er punto de la señal 2, el 2do punto de la señal 1 con el 2do punto de la señal 2, y así sucesivamente), el resultado será que la computadora detectará dos señales distintas (cuando son la misma con una ligera variación).

DTW nos permite estirar y encoger ambas señales para tratar de hacerlas coincidir lo mejor posible, de esta manera, si presentan el mismo patrón ambas señales, el algoritmo logrará reconocerlas con mayor exactitud.

 

 

 

 

 

 

 

Como se ve en la figura de arriba, el algoritmo tratará de encontrar las coincidencias entre ambas señales.

Ahora supongamos que tenemos las siguientes señales, utilizaré numeros enteros para hacerlo más sencillo:

S1= 1 1 1 2 2 1 3 3 5

S2= 1 1 2 1 3 5

Vemos que la señal 1 (S1) es más larga que la señal 2 (S2), aún asi, hay manera de ajustar ambas señales. Para hacerlo haremos uso de una matriz de tamaño n x m, donde n es la longitud de S1 y m la longitud de S2, para el ejemplo anterior, tendremos una matriz de 9×6. En esta matriz almacenaremos la distancia entre cada uno de los puntos de S1 y S2, esto lo haremos restando los puntos de S1 y S2:

 

 

 

 

 

 

 

Continuará…

 

Bien, a continuación hablaremos del análisis de algoritmos que es una técnica utilizada para calcular el costo computacional de diversos algoritmos. El análisis de los algoritmos es importante debido a que, en más de una ocasión tendremos varios algoritmos entre los cuales elegir para realizar exactamente la misma tarea pero con diferente método, y deberemos saber cuál de todos ellos requiere de menor costo computacional (el que se encuentre en menor orden, después hablaremos de esto). Para ello abordaremos en varios post las diferentes técnicas utilizadas, asi que sean pacientes, es necesario que conozcan varios conceptos básicos que trataré de explicar sencillamente a lo largo de varios post.

 

Primero es necesario entender los siguientes conceptos:

Operador elemental: operación cuyo tiempo de ejecución está delimitado por una constante, donde esta constante depende de la implementación que hayamos hecho del algoritmo (en qué lenguaje, en que máquina…). Por ejemplo, supongamos que estamos analizando un algoritmo y encontramos que para resolver un caso de cierto tamaño se requieren a adiciones, b multiplicaciones y c instrucciones de asignación. Supongamos tambien que se sabe que las adiciones no pueden tomar mas de ta microsegundos, que una multiplicación no requiere más de tb microsegundos, y una instrucción de asignación no requiere más de tc microsegundos, donde ta,tb y tc son constantes que dependen de la máquina que estemos usando. Dado que el costo de cada una de estas operaciones está delimitado por una constante, pueden ser consideradas operaciones elementales. Entonces el tiempo total t necesario para ejecutar nuestro algoritmo estará acotado por:

t ≤ at+ bt+ ctc                         (1)

t ≤ max (ta, tb, tc) x (a,b,c)            (2)

Esto es: se toma el mayor de los costos de las diferentes operaciones elementales, y se asume que las demás operaciones elementales también tienen ese costo. Dado que el costo exacto de cada operación elemental en realidad no es tan importante, simplificaremos diciendo que cada operación elemental tiene un costo unitario. Sin embargo, existen algunas excepciones, por ejemplo: la suma de aquellos números que no alcanzan a ser representados de manera simple en una computadora (numero muy grandes, con decimales muy largos y pequeños, entre otros), y que requieren de un trato especial al sumarlos, restarlos, dividirlos, multiplicarlos… en estos casos, estas operaciones no son consideradas elementales, sin embargo, dejaremos estos casos fuera del alcance de este blog.

Análisis del algoritmo, mejor, medio y peor caso: En el análisis de un algoritmo, no necesariamente hay una respuesta absoluta con respecto a su análisis. Habrá que considerar que podemos analizar el mismo algoritmo utilizando enfoques diferentes. Podemos hacer el análisis basándonos en el mejor de los casos, esto es, cuando el algoritmo ejecuta el menor número de operaciones. Para el mismo algoritmo, podemos basarnos en el peor de los casos, que es cuando el algoritmo realiza el mayor número de operaciones, por lo que el análisis para el mismo algoritmo en el mejor y peor de los casos, será diferente. Y bueno finalmente, está el análisis del caso medio, que creo que ya se entiende.

Para entender lo anterior, pongamos el primer ejemplo:

 

 

 

 

 

 

El código de arriba corresponde a un algoritmo de ordenamiento, donde t es un arreglo que contiene los elementos a ordenar. Supongamos que t={1,2,3,4,5}, si analizamos el comportamiento del algoritmo podemos observar que dado que los números ya están ordenados, el algoritmo no tendrá que hacer ningún intercambio y por tanto nos ahorramos muchas operaciones.

Por el contrario, si t={5,4,3,2,1}, entonces habría que recorrer todo el arreglo, e intercambiar cada uno de los números para lograr que queden ordenados. Por lo tanto no nos ahorramos ninguna operación, ya que se ejecutan todas las posibles en el algoritmo.

En estos dos ejemplos, el primero se considera el mejor de los casos, debido a que se ejecuta el menor número de operaciones posibles en el algoritmo, por otro lado, el segundo ejemplo es considerado el peor de los casos debido a que ejecuta el mayor número de operaciones posibles.

Ahora bien, en caso de que t={5,2,3,1,4}, no se ejecuta el menor número de operaciones posibles pero tampoco el mayor número, así que por ello es considerado el caso medio.

En el próximo post, estudiaremos la notación asintótica y como establecer el orden de un algoritmo en términos de ella.

Cualquier duda, favor de dejar en comentarios =).