lunes, 29 de abril de 2013

[offtopic] Medidor de distancias

De chico siempre me divertí mucho jugando con ojos. Los mios, claro. Así descubrí dos de los tres mecanismos que sirven para calcular la distancia a las cosas.


Uno de los mecanismos es el enfoque de cada ojo, que se usa a distancias cortas. Cuando el ojo esta enfocando correctamente, el cerebro sabe cuanto esfuerzo está haciendo y la distancia que corresponde.




El otro es la alineación de ambos. Para ver cerca uno vizquea, las lineas de visión convergen cerca si miramos algo cercano, tienden a ponerse paralelas al mirar a lo lejos. Este mecanismo funciona a corta y media distancia.


Existe un truco para extender la alineación, que es moverse lateralmente y viene a ser como separar los ojos.

El tercer mecanismo es la apreciación de la perspectiva y el tamaño aparente  que esperamos de las cosas que además, agrega la posibilidad de apreciar diferencias de distancias mayores.




Combinamos los tres mecanismos para tener el cuadro completo, es por eso que los tuertos no pueden apreciar ni las películas en 3d ni los estereogramas ni los ciegos ningún tipo de película.



Las ilusiones ópticas se basan en manipular algunos de estos mecanismos para engañar al cerebro.





En este caso tenemos varios indicios de que no se trata de un camello real:

  • Está fuera de foco.
  • Aunque parece estar entrando por la puerta, está sobre una de las hojas.
  • Es un poco pequeño en relación a la persona, más considerando que está pisando más cerca.
  • Y fundamentalmente, no es habitual ver camellos en los livings.
Esto no quita que alguna personita se lo haya creido.

Todo esto que he explicado se basa exclusivamente en mi experiencia y reflexión, no he recurrido a ninguna fuente. Calculo (y espero) que a grandes rasgos sea correcto.


Muchos años despues fui al museo naval en Tigre y vi un artefacto que era como un largavistas, pero con unos espejos que separaban las lineas de visión tres metros. Aunque no lo pude usar, intuí que manipulándo la alineación, cuando uno veía las dos imágenes coincidir, podía saber la distancia. Mientras buscaba una imagen, encontré un artículo muy interesante del '39 para hacer un mecanismo con un cartoncito. [1]

Finalmente, hace unos meses, imaginándome en el medio del campo, me pregunté que haría yo con los recursos con los que cuento para saber a que distancia estaban las cosas y ahí fue que nació este proyecto[2].





La idea es separar los ojos pero en lugar de usar un mecanismo óptico mecánico, usar cámaras conectadas a una computadora. Como está completamente fuera de mi habilidad ajustar y medir la alineación de las cámaras, trabajo superponiendo y alineando las imágenes generadas.



Esta manera tiene la ventaja de requerir muy poco ajuste y permite utilizar una distancia mucho mayor entre las cámaras, que en caso de proveer la resolución apropiada, podrían lograr una precisión bastante alta.

Muchas gracias a Greta Luna por las ilustraciones[3].

 

 

Implementación


Apesta.


No he tenido mucha oportunidad de utilizar ninguna metodología de desarrollo, el modelo se reduce a unas sencillas operaciones entre matrices y mantener unos pocos estados. La aplicación no es absolutamente sencilla y bien hecha por que no usé qt-designer, que me hubiera armado todo, pero yo no hubiera aprendido tanto. Conozco "la optimización prematura es la raiz de todo mal", lo sensato hubiese sido usar php, ruby o python y despues pasar a c++ en caso de necesidad. Trasca, los proyectos en lenguajes interpretados además son más fáciles de compartir. Lo hice en c++ por que deseaba practicar.

Elegí qt[4] por que encontré rápido que se llevaba bien[5] con vlc[6], asi me puedo abstraer totalmente de las fuentes de video, pudiendo ser cámaras, videos archivados (muy cómodos para hacer pruebas) y fundamentalmente streaming, lo que permite usar dos computadoras bastante alejadas entre si, cosa que sin embargo aún no he logrado.

Para hallar el modelo tomé medidas y aposté a que se resolvía con tres puntos de referencia y una cuadrática[7][8]. Puse las medidas en una planilla y comparé con la cuadrática que me daba el método de la matriz inversa y funcionó.


El uso del programa se reduce a ajustar las cámaras para que esten apuntando al mismo lugar, tomar referencias de tres puntos de distancia creciente y utilizar.

Lo que falta


Hay un importante problema con la resolución derivado de la baja calidad de la solución. Por mis limitados conocimientos, yo estoy volcando el stream de vlc en un widget del cual hago un snapshot que proceso y pego en otro widget. Esto produce que en lugar de trabajar con la resolución del stream lo haga con la del render del widget. Es por eso que se ven las tres imágenes del mismo tamaño, cuando bien podría verse una sola o verse la central más grande. Había pensado en usar la resolución real en las vistas laterales y ocultarlas, pero vlc y qt tienen la suficiente inteligencia como para no hacer render de lo que no se vé. OpenCV[9] podría ayudar, pero recién lo consideré al pensar que el programa podría calcular distancias automáticamente, por ejemplo de caras.


Dado que el 95% del alcance original está alcanzado, por ahora estoy feliz. El que mucho abarca, poco aprieta.

La arquitectura actual es:

  stream --> vlc --> qt ----------------> render izquierda
                     +--> mixer -->qt --> render mezcla
  stream --> vlc --> qt ----------------> render derecha

mientras que la correcta sería:

  stream --> vlc opcional --> opencv -----------> qt --> render izquierda
                                +-----> mixer --> qt --> render mezcla
  stream --> vlc opcional --> opencv -----------> qt --> render derecha

Dejo vlc por el network streaming y puse opencv pero pudo haber sido otra cosa.


Hay algunas mejorías que quizás algún día haga:
  • Que funcionen bien los modos de refresco de la pantalla de mezcla, es el 5% que me falta. (me da mucha pereza, lo voy a dejar tras rehacer con qt-designer)
  • Rehacer usando qt-designer (útil para aprender)
  • Guardar y restaurar configuraciones (sencillo y útil)
  • Integrar con GPS (no tengo gps...)

Pasos


git clone https://github.com/cpantel/cheapRangeFinder.git

make -j3/5/x

Dependencias

make
g++
qt-designer (instala todo lo necesario para qt)
libvlc-dev

Referencias


[1] http://www.dofmaster.com/rangefinder.html
[2] https://github.com/cpantel/cheapRangeFinder
[3] http://lanilunatejidos.blogspot.com.ar/
[4] https://qt-project.org/
[5] https://wiki.videolan.org/LibVLC_SampleCode_Qt
[6] http://www.videolan.org/
[7] http://math.uww.edu/~mcfarlat/matrix.htm Inverse Matrix Method
[8] http://www.dr-lex.be/random/matrix_inv.html inverse and determinant of 2x2 and 3x3 matrices

[9] http://opencv.org

No hay comentarios:

Publicar un comentario