Detección de movimiento con WebCam
- publicado por Ing. Jesús Martínez
- Fecha septiembre 7, 2023
Contenido:
Material:
- Laptop, PC o Raspberry
- WebCam
Introducción:
¿Alguna vez has deseado tener un sistema de seguridad simple pero efectivo para tu hogar o espacio de trabajo? ¡Hoy estás de suerte! En esta entrada de blog, te guiaré paso a paso a través de la creación de un código en Python que te permitirá realizar la detección de movimiento en tiempo real utilizando tu webcam. Esta emocionante aplicación te ayudará a estar al tanto de cualquier actividad inusual en tu entorno. Sin más preámbulos, echemos un vistazo al código y descubramos cómo funciona
Desarrollo:
Comencemos importando la librería con la cual trabajaremos, esta es OpenCV
import cv2
Ahora inicializaremos la cámara con la cual trabajaremos, esta selección la realizaremos con números enteros, es decir, si tienes una cámara conectada, esta será el numero 0, pero si tienes 2 cámaras conectadas, una será el numero 0 y la segunda el numero 1, en este caso solo cuento con una cámara conectada, por lo tanto su índice es el 0.
cap = cv2.VideoCapture(0)
Para realizar la detección de movimiento, debemos capturar un primer frame, el cual servirá como una escena de muestra, es decir que el código intentará detectar todos los cambios en la escena capturada en los siguientes frames. Por lo tanto, el siguiente bloque de código nos quedaría de la siguiente manera.
ret, frame1 = cap.read()
frame1Gray= cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)# se convierte en escala de grises
Ahora debemos capturar frames de manera sucesiva, convertir cada nuevo frame en escala de grises, obtener su diferencia absoluta y después a esa escena con las diferencias aplicarle una binarización para resaltar dichas diferencias. A esa nueva escena le extraeremos los contornos y los aproximaremos a rectángulos para que dichas diferencias sean más notables en la imagen final.
while True:
ret, frame2 = cap.read()
frame2Gray = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
diferencia = cv2.absdiff(frame1Gray, frame2Gray)
_, umbral = cv2.threshold(diferencia, 30, 255, cv2.THRESH_BINARY)
contornos, _ = cv2.findContours(umbral, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contorno in contornos:
if cv2.contourArea(contorno) > 500:
(x, y, w, h) = cv2.boundingRect(contorno)
cv2.rectangle(frame2, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("Detección de Movimiento", frame2)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
Perfecto, ahora solo resta liberar la cámara y destruir todas las ventanas generadas por OpenCV
cap.release()
cv2.destroyAllWindows()
Resultados:
Por lo tanto, nuestro código final quedaría de la siguiente manera
import cv2
cap = cv2.VideoCapture(0)
ret, frame1 = cap.read()
frame1Gray = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
while True:
ret, frame2 = cap.read()
frame2Gray = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
diferencia = cv2.absdiff(frame1Gray, frame2Gray)
_, umbral = cv2.threshold(diferencia, 30, 255, cv2.THRESH_BINARY)
contornos, _ = cv2.findContours(umbral, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contorno in contornos:
if cv2.contourArea(contorno) > 500:
(x, y, w, h) = cv2.boundingRect(contorno)
cv2.rectangle(frame2, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("Detección de Movimiento", frame2)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Pero espera, aún hay más, en algunas ocasiones, la cámara captura el primer frame algo oscuro o totalmente oscuro, por lo tanto, muchas de las veces es recomendable sacrificar los primero frames, realicemos algunas modificaciones al código.
import cv2
cap = cv2.VideoCapture(0)
cuenta = 0
while True:
if cuenta < 10:
ret, frame1 = cap.read()
frame1Gray = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
cuenta +=1
else:
ret, frame2 = cap.read()
frame2Gray = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
diferencia = cv2.absdiff(frame1Gray, frame2Gray)
_, umbral = cv2.threshold(diferencia, 30, 255, cv2.THRESH_BINARY)
contornos, _ = cv2.findContours(umbral, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contorno in contornos:
if cv2.contourArea(contorno) > 500:
(x, y, w, h) = cv2.boundingRect(contorno)
cv2.rectangle(frame2, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("Detección de Movimiento", frame2)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Recordemos que este código solo detecta lo cambios en comparación con el frame que se captura al inicio, pero ¿que pasaría si quisiéramos que cada ciclo sea un nuevo frame de comparación?, pues solo es cuestión de agregar una simple línea de código, en donde igualaremos el nuevo frame 1 al frame 2 y listo, veamos el nuevo código.
import cv2
cap = cv2.VideoCapture(0)
cuenta = 0
while True:
if cuenta < 10:
ret, frame1 = cap.read()
frame1Gray = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
cuenta +=1
else:
ret, frame2 = cap.read()
frame2Gray = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
diferencia = cv2.absdiff(frame1Gray, frame2Gray)
_, umbral = cv2.threshold(diferencia, 30, 255, cv2.THRESH_BINARY)
contornos, _ = cv2.findContours(umbral, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contorno in contornos:
if cv2.contourArea(contorno) > 500:
(x, y, w, h) = cv2.boundingRect(contorno)
cv2.rectangle(frame2, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("Detección de Movimiento", frame2)
frame1Gray = frame2Gray
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Soy un apasionado por la innovación tecnológica, el desarrollo y el emprendimiento. Durante mi educación superior me enfoqué en la programación de software para visión artificial e inteligencia artificial. Poco después al graduarme tuve la oportunidad de aplicar estos conocimientos en el desarrollo de soluciones para empresas como General Motors, Ford, Harley-Davidson, Mack, Tesla y unas cuantas empresas más del ramo automotriz.