El Flujo Óptico


En esta semana me puse a revisar algunos algoritmos de ejemplo que traen las librerías de OpenCvSharp, y me dí con el de flujo óptico. Cuando trabaje con processing deseaba poder implementar algún algoritmo de este tipo, pero las librerías de opencv para processing no me soportaban la cámara y por la inexperiencia de esos días no entendía como hacerlo y me conforme con la detección de movimiento para poder construir juegos para niños. Ahora con un poco más de experiencia y armado de un marco mucho más rico de funciones dentro de OpenCV para C#,  he adaptado el algoritmo de ejemplo que trae y  poder mover un pequeño cuadrado (pensar que para animar un simple cuadrado tuve que romperme la cabeza con processing… hace algunos años).

Algo de teoría

Flujo óptico

El flujo óptico sucede cuando nos movemos en una dirección determinada. Si miramos hacia el punto al que nos dirigimos (el centro de expansión) éste no muestra movimiento, mientras que si miramos al espacio circundante, el campo visual parece expandirse. Este efecto, nuestro cerebro lo percibe con  precisión, y  contribuye al control de la locomoción.

El objetivo inmediato del análisis de imágenes basado en el flujo óptico es determinar el campo de movimiento (representación bidimensional de un movimiento tridimensional)

Algoritmo de Lucas-Kanade

Asumen constantes los vectores de velocidad u y v en una pequeña porción de la imagen.

lucas_a

lucas1

lucas_b

donde la matriz A contiene las derivadas espaciales de la imagen, el vector v corresponde al vector de flujo óptico (u,v) y el vector b contiene las derivadas temporales de la imagen.

lucas_c

lucas2

lucas_d

Para poder realizar el cálculo de flujo óptico tiene que ser posible la inversión de la matriz

lucas_e

Shi y Tomassi definen en las propiedades que debe cumplir una región para que el flujo óptico se estimado apropiadamente utilizando la técnica de LK. Sean λ1 y λ2 los valores propios de la matriz $$A^TA$ para cierta región R de la imagen, entonces se debe cumplir que:

  • min (λ1 y λ2) > λmin) existe en R
  • (λ1 / λ2) < t

Veamos la implementación del algoritmo original ofrecido dentro de los ejemplo de OpenCvSahrp

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OpenCvSharp.Test
{
/// <summary>
/// Lucas & Kanade アルゴリズムによるオプティカルフローの計算
/// </summary>
/// <remarks>http://opencv.jp/sample/optical_flow.html#optflowHSLK</remarks&gt;
class OpticalFlowLK
{
public OpticalFlowLK()
{
using (IplImage srcImg1 = Cv.LoadImage(Const.ImagePenguin1, LoadMode.GrayScale))
using (IplImage srcImg2 = Cv.LoadImage(Const.ImagePenguin1b, LoadMode.GrayScale))
using (IplImage dstImg = Cv.LoadImage(Const.ImagePenguin1b, LoadMode.Color))
{
// (1)速度ベクトルを格納する構造体の確保,等
int cols = srcImg1.Width;
int rows = srcImg1.Height;
using (CvMat velx = Cv.CreateMat(rows, cols, MatrixType.F32C1))
using (CvMat vely = Cv.CreateMat(rows, cols, MatrixType.F32C1))
{
Cv.SetZero(velx);
Cv.SetZero(vely);

// (2)オプティカルフローを計算
Cv.CalcOpticalFlowLK(srcImg1, srcImg2, Cv.Size(15, 15), velx, vely);

// (3)オプティカルフローを描画
for (int i = 0; i < cols; i += 5)
{
for (int j = 0; j < rows; j += 5)
{
int dx = (int)Cv.GetReal2D(velx, j, i);
int dy = (int)Cv.GetReal2D(vely, j, i);
Cv.Line(dstImg, Cv.Point(i, j), Cv.Point(i + dx, j + dy), Cv.RGB(255, 0, 0), 1, Cv.AA, 0);
}
}

// (4)オプティカルフローの表示
Cv.NamedWindow(“ImageLK”, WindowMode.AutoSize);
Cv.ShowImage(“ImageLK”, dstImg);
Cv.NamedWindow(“velx”, WindowMode.AutoSize);
Cv.ShowImage(“velx”, velx);
Cv.NamedWindow(“vely”, WindowMode.AutoSize);
Cv.ShowImage(“vely”, vely);
Cv.WaitKey(0);
Cv.DestroyAllWindows();
}
}

}
}
}

Aquí el video de la implementación del algoritmo en tiempo real:

Y este video con el movimiento detectado sobre un cuadrado:

Juan Cadillo

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s