Detección de movimiento OpenCV

Salman Mehmood 10 octubre 2023
Detección de movimiento OpenCV

En este artículo, aprenderemos cómo podemos crear un proyecto de detección de movimiento con la ayuda de OpenCV y Python.

Cree un proyecto de detección de movimiento usando OpenCV y Python

En primer lugar, hablemos de los requisitos de este proyecto. El primer requisito obviamente será necesario para instalar Python, y también necesitamos instalar un paquete externo que se llama opencv.

Necesitamos abrir el símbolo del sistema y ejecutar este comando para instalar este paquete en su PC. Vayamos a nuestro editor y comencemos a escribir nuestro código.

Lo primero que importaremos son nuestras bibliotecas requeridas, cv2 y time, y lo siguiente es que tomaremos los datos de nuestra cámara web usando el método VideoCapture() de OpenCV.

Vamos a crear un objeto llamado Video, y tenemos que pasar 0 a VideoCapture() porque estamos usando el canal 0 para la cámara web.

import cv2
import time

Video = cv2.VideoCapture(0)
First_Frame = None

Ahora crearemos un bucle while True o un bucle infinito porque extraeremos un video, y un video es el movimiento continuo en una presentación de diapositivas de imágenes.

Ahora definiremos varias instrucciones en un bucle while, y en la primera línea crearemos dos variables, Check y frame, y leeremos los datos extraídos por el método VideoCapture(). En la siguiente instrucción, convertiremos esta imagen extraída a escala de grises.

Pero, ¿por qué estamos convirtiendo esto en escala de grises? Estamos haciendo esto porque queremos aumentar la precisión de la detección de características.

Usamos el método cvtColor() para cambiar a escala de grises y tenemos dos parámetros. Primero está el marco o una imagen que queremos convertir a escala de grises, y luego el siguiente es COLOR_BGR2GRAY, que convertirá una imagen a color gris.

Ahora haremos que una imagen se vuelva borrosa o suavizada, por lo que la detección de objetos o el movimiento de un objeto será mucho más fácil. Usamos el método GaussianBlur() para aplicar suavizado y pasarle una imagen en escala de grises, tamaño de núcleo y sigma.

while True:
    Check, frame = Video.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    gray = cv2.GaussianBlur(gray, (21, 21), 0)

Crearemos una declaración if que verificará si el marco viene o no, y estamos haciendo esto porque queremos el Primer_Frame como nuestro marco de referencia.

Echemos un vistazo a lo que dice la física sobre el movimiento. El movimiento se identifica desde un punto de referencia, y lo explicamos con un ejemplo.

Digamos que estás sentado en un tren, y para ti, los árboles se mueven, pero no se mueven; están quietos, pero te estás moviendo desde tu punto de referencia. En ese caso, los árboles son puntos de referencia, pero el marco es una referencia en nuestro caso.

Estamos fijando el First_Frame como nuestro marco de referencia; si ocurre algún cambio desde el marco de referencia, entonces podemos decir que el movimiento está ahí.

Ahora estableceremos una declaración como si la variable First_Frame es None, que es true en el primer caso, luego haremos que la variable First_Frame sea igual a la imagen en escala de grises que es la variable gris.

if First_Frame is None:
    First_Frame = gray
    continue

Usaremos el método absdiff() para encontrar la diferencia entre los cuadros. Vamos a crear una variable de marco delta y pasar los dos parámetros al método absdiff() para comparar.

Necesitamos establecer un umbral o un límite en el que queremos que se detecte el movimiento porque no queremos que los ruidos se detecten como movimiento.

Para ello utilizamos el método threshold(), y tiene unos parámetros, primero es el delta_frame, el segundo es la intensidad, el tercero es el tono de color que en este caso es blanco, y luego el el siguiente es THRESH_BINARY ya que es una tupla, por lo que debemos seleccionar el primer elemento.

También necesitamos aplicar una capa más de suavizado en la siguiente instrucción. Para hacer esto, necesitamos usar una función de suavizado más llamada dilate(), y acepta tres parámetros, el primero es el threshold, el segundo es None, y el tercer parámetro es el iterations.

El parámetro iteraciones define qué tan preciso será su suavizado; su programa también capturará los ruidos si aumenta el valor de este parámetro.

Esta vez crearemos los contornos, entonces, ¿qué son los contornos? Los contornos son los puntos en los que ocurre el movimiento.

Si el marco está quieto y la mano se está moviendo, entonces la parte de la mano es el contorno.

El método findContours() ayuda a encontrar contornos y acepta tres parámetros, primero es el marco, y estamos usando el método copy() para crear la copia de la matriz de marcos.

delta_frame = cv2.absdiff(First_Frame, gray)
Threshold_frame = cv2.threshold(delta_frame, 50, 255, cv2.THRESH_BINARY)[1]
Threshold_frame = cv2.dilate(Threshold_frame, None, iterations=2)
(cntr, _) = cv2.findContours(
    Threshold_frame.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)

Ahora obtendremos contornos a través de la iteración y definiremos el área aproximada para que sea un movimiento. Si no delimitamos el área, obtendremos una detección de movimiento muy ruidosa.

En primer lugar, comprobaremos que si el área del contorno es menor que mil, entonces no consideramos esto como un área de movimiento, y continuaremos la iteración, y si es mayor que mil, entonces dibujaremos un triángulo.

for contour in cntr:
    if cv2.contourArea(contour) < 1000:
        continue

El método findContours() da cuatro valores (x, y, alto, ancho), y extraeremos estos puntos usando el método boundingRect(), que unirá el área del rectángulo. Ahora crearemos el rectángulo con la ayuda del método rectangle().

El primer parámetro es el frame o imagen sobre la que queremos dibujar el rectángulo. El siguiente son los puntos de coordenadas (x,y), el siguiente es el alto y el ancho, el siguiente es el color del marco y el último parámetro es el tamaño del lápiz seleccionado para dibujar el rectángulo.

(x, y, w, h) = cv2.boundingRect(contour)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)

Código fuente completo:

import cv2
import time

Video = cv2.VideoCapture(0)
First_Frame = None

while True:
    Check, frame = Video.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    gray = cv2.GaussianBlur(gray, (21, 21), 0)
    if First_Frame is None:
        First_Frame = gray
        continue
    delta_frame = cv2.absdiff(First_Frame, gray)
    Threshold_frame = cv2.threshold(delta_frame, 50, 255, cv2.THRESH_BINARY)[1]
    Threshold_frame = cv2.dilate(Threshold_frame, None, iterations=2)
    (cntr, _) = cv2.findContours(
        Threshold_frame.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
    )
    for contour in cntr:
        if cv2.contourArea(contour) < 1000:
            continue
        (x, y, w, h) = cv2.boundingRect(contour)
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)
    cv2.imshow("Frame", frame)
    Key = cv2.waitKey(1)
    if Key == ord("q"):
        break

Video.release()
cv2.destroyAllWindows()

Ahora podemos ver que la detección de movimiento ocurre cuando la mano se está moviendo.

Cree un proyecto de detección de movimiento usando OpenCV y Python

Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn

Artículo relacionado - OpenCV Video