Filtro de Kalman usando OpenCV en Python

Manav Narula 30 enero 2023
  1. Filtro de Kalman usando opencv en Python
  2. Conclusión
Filtro de Kalman usando OpenCV en Python

Computer Vision aborda varias tareas complicadas asociadas con el procesamiento de imágenes y videos en Inteligencia Artificial. Usamos la biblioteca opencv de Python para manejar algunas de estas tareas.

Esta biblioteca implementa diferentes algoritmos y técnicas utilizando objetos para abordar algunos de estos problemas.

Una de esas tareas es predecir la trayectoria de un objeto dado. Uno de los algoritmos más comunes utilizados para esto es el filtro de Kalman.

Este tutorial demostrará el filtro de Kalman usando opencv en Python.

Filtro de Kalman usando opencv en Python

El filtro de Kalman utiliza el estado anterior del objeto para predecir su próximo estado. Este algoritmo utiliza una ecuación diferencial estocástica lineal para determinar el siguiente estado.

Necesitamos estar familiarizados con algunas matrices asociadas con esta ecuación.

Primero, una matriz de transición de estado vincula el estado actual con el estado anterior. Opcionalmente, podemos controlar la entrada usando una matriz de entrada de control.

Necesitamos transformar el estado en algún dominio de medición que se logra utilizando una matriz de transformación. También es necesario que haya un vector de ruido de proceso con covarianza.

En Python, podemos usar la clase KalmanFilter de la biblioteca opencv para implementar este algoritmo y predecir estados. Definiremos los atributos de un objeto para esta clase y asignaremos las matrices necesarias.

Los atributos measurementMatrix, transitionMatrix y processNoiseCov especifican la matriz de medición, la matriz de transición y la matriz de ruido del proceso con covarianza discutidas anteriormente, respectivamente. Luego podemos usar el objeto para hacer algunas predicciones usando la función predict().

Entendamos esto mejor con un ejemplo.

import cv2
import numpy as np

measured = []
predicted = []
dr_frame = np.zeros((400, 400, 3), np.uint8)
mp = np.array((2, 1), np.float32)
tp = np.zeros((2, 1), np.float32)


def on_mouse(k, x, y, s, p):
    global mp, measured
    mp = np.array([[np.float32(x)], [np.float32(y)]])
    measured.append((x, y))


def paint_canvas():
    global dr_frame, measured, predicted
    for i in range(len(measured) - 1):
        cv2.line(dr_frame, measured[i], measured[i + 1], (0, 100, 0))
    for i in range(len(predicted) - 1):
        cv2.line(dr_frame, predicted[i], predicted[i + 1], (0, 0, 200))


def reset_canvas():
    global measured, predicted, dr_frame
    measured = []
    predicted = []
    dr_frame = np.zeros((400, 400, 3), np.uint8)


cv2.namedWindow("Sample")
cv2.setMouseCallback("Sample", on_mouse)
kalman_fil = cv2.KalmanFilter(4, 2)
kalman_fil.measurementMatrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0]], np.float32)
kalman_fil.transitionMatrix = np.array(
    [[1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]], np.float32
)
kalman_fil.processNoiseCov = (
    np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]], np.float32)
    * 0.03
)

while True:
    kalman_fil.correct(mp)
    tp = kalman_fil.predict()
    predicted.append((int(tp[0]), int(tp[1])))
    paint_canvas()
    cv2.imshow("Output", dr_frame)
    k = cv2.waitKey(30) & 0xFF
    if k == 27:
        break
    if k == 32:
        reset_canvas()

Producción:

Filtro Kalman usando opencv en Python

En el ejemplo anterior, implementamos el filtro de Kalman y lo usamos para predecir el movimiento de nuestro mouse. Creamos un lienzo y movemos el cursor sobre este lienzo (color verde), y simultáneamente el filtro de Kalman intentará predecir el movimiento del cursor (color rojo).

Entendamos lo que está sucediendo en el código.

Comenzamos creando un marco de lienzo en el que podemos dibujar el movimiento del cursor. La función on_mouse() se usa para agregar los valores del cursor.

El método paint_canvas() toma estos valores y los valores predichos y los dibuja en el lienzo. La función setMouseCallback() también se llama cada vez que se mueve el cursor.

Creamos una clase KalmanFilter llamada objeto kalman_fil. Las matrices requeridas se asignaron utilizando los atributos discutidos anteriormente.

Luego ejecutamos un bucle para dibujar en el lienzo y hacer las predicciones.

El método correct() de esta clase actualiza el estado predicho de la medición. La función predict() hace las predicciones.

Estos valores predichos se dan al método paint_canvas().

Para salir del bucle, usamos la declaración break, y se llama cuando el usuario presiona la tecla Esc (tecla número 27 en el teclado). Si pulsamos la barra espaciadora, el lienzo se borra de la medida anterior llamando al método reset_canvas().

Conclusión

Para concluir, discutimos los conceptos básicos de un filtro Kalman en este tutorial. Discutimos la lógica necesaria y los atributos detrás de esto.

Implementamos este algoritmo utilizando la clase KalmanFilter de la biblioteca opencv. Se demostraron diferentes parámetros y funciones miembro de esta clase.

Usamos el algoritmo para predecir el movimiento del cursor en un lienzo de dibujo.

Manav Narula avatar Manav Narula avatar

Manav is a IT Professional who has a lot of experience as a core developer in many live projects. He is an avid learner who enjoys learning new things and sharing his findings whenever possible.

LinkedIn