Procesamiento de video C++ OpenCV
El procesamiento de video se refiere al procesamiento y análisis de cada fotograma de imagen en una secuencia de video.
OpenCV proporciona potentes herramientas para procesar datos de video, incluyendo lectura de video, procesamiento de fotogramas, guardado de video y procesamiento de video en tiempo real.
Escenarios de aplicación del procesamiento de video
Vigilancia por video:
Usar sustracción de fondo para detectar objetos en movimiento.
Usar flujo óptico para analizar las trayectorias de movimiento de objetos.
Análisis de video:
Extraer fotogramas clave del video.
Analizar el comportamiento de objetos en el video.
Procesamiento en tiempo real:
Filtros de video en tiempo real (como detección de bordes, desenfoque, etc.).
Detección y seguimiento de objetos en tiempo real.
Lectura y visualización de video
Lectura de archivos de video (VideoCapture)
En OpenCV,VideoCapturela clase se utiliza para leer fotogramas de video desde archivos de video o cámaras.
Para leer un archivo de video, primero debe crear unVideoCaptureobjeto y especificar la ruta del archivo de video.
Ejemplo
using namespace cv;
int main() {
// Crear un objeto VideoCapture y abrir el archivo de video
VideoCapture cap("example.mp4");
// Verificar si el video se abrió correctamente
if (!cap.isOpened()) {
std::cerr << "Error: Could not open video file." << std::endl;
return -1;
}
// El código de lectura y visualización de video se presentará a continuación
return 0;
}
Mostrar fotogramas de video
Después de leer el archivo de video, puede leer el video fotograma a fotograma en un bucle y usarimshowla función para mostrar cada fotograma.
Ejemplo
while (true) {
// Leer el siguiente fotograma
cap >> frame;
// Si el fotograma está vacío, significa que el video ha terminado
if (frame.empty()) {
break;
}
// Mostrar el fotograma actual
imshow("Video", frame);
// Esperar 30 milisegundos, presionar ESC para salir
if (waitKey(30) == 27) {
break;
}
}
// Liberar el objeto VideoCapture
cap.release();
// Cerrar todas las ventanas
destroyAllWindows();
Guardar video (VideoWriter)
Si desea guardar el video procesado en un archivo, puede usarVideoWriterla clase. Primero debe especificar el nombre del archivo de salida, el códec, la velocidad de fotogramas y el tamaño del fotograma.
Ejemplo
double fps = cap.get(CAP_PROP_FPS);
Size frameSize(cap.get(CAP_PROP_FRAME_WIDTH), cap.get(CAP_PROP_FRAME_HEIGHT));
// Crear un objeto VideoWriter
VideoWriter writer("output.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), fps, frameSize);
while (true) {
cap >> frame;
if (frame.empty()) {
break;
}
// Escribir el fotograma en el archivo de video de salida
writer.write(frame);
imshow("Video", frame);
if (waitKey(30) == 27) {
break;
}
}
// Liberar los objetos VideoCapture y VideoWriter
cap.release();
writer.release();
destroyAllWindows();
Procesamiento de fotogramas de video
Procesamiento de video fotograma a fotograma
En el procesamiento de video, generalmente es necesario realizar operaciones específicas en cada fotograma. Por ejemplo, se puede convertir cada fotograma a escala de grises, aplicar detección de bordes, etc.
Ejemplo
cap >> frame;
if (frame.empty()) {
break;
}
// Convertir el fotograma a imagen en escala de grises
Mat grayFrame;
cvtColor(frame, grayFrame, COLOR_BGR2GRAY);
// Mostrar el fotograma en escala de grises
imshow("Gray Video", grayFrame);
if (waitKey(30) == 27) {
break;
}
}
Procesamiento en tiempo real de fotogramas de video
Al procesar fotogramas de video en tiempo real, generalmente es necesario aplicar algunos algoritmos de procesamiento en tiempo real en cada fotograma. Por ejemplo, detectar objetos en movimiento en el video en tiempo real.
Ejemplo
cap >> prevFrame;
cvtColor(prevFrame, prevFrame, COLOR_BGR2GRAY);
while (true) {
cap >> nextFrame;
if (nextFrame.empty()) {
break;
}
cvtColor(nextFrame, nextFrame, COLOR_BGR2GRAY);
// Calcular la diferencia entre fotogramas
absdiff(prevFrame, nextFrame, diffFrame);
// Mostrar el fotograma de diferencia
imshow("Motion Detection", diffFrame);
// Actualizar el fotograma anterior
prevFrame = nextFrame.clone();
if (waitKey(30) == 27) {
break;
}
}
Procesamiento en tiempo real con cámara
Abrir cámara
UsandoVideoCapturela clase no solo puede leer archivos de video, sino que también puede abrir la cámara para procesar flujos de video en tiempo real. Para abrir la cámara, solo necesitaVideoCaptureestablecer el parámetro en 0 (que indica la cámara predeterminada).
Ejemplo
if (!cap.isOpened()) {
std::cerr << "Error: Could not open camera." << std::endl;
return -1;
}
Procesamiento de flujos de video en tiempo real
Después de abrir la cámara, puede procesar el flujo de video en tiempo real fotograma a fotograma, igual que con archivos de video. Por ejemplo, puede aplicar algoritmos de detección de bordes en el flujo de video en tiempo real.
Ejemplo
cap >> frame;
if (frame.empty()) {
break;
}
// Aplicar detección de bordes Canny
Mat edges;
Canny(frame, edges, 100, 200);
// Mostrar el resultado de la detección de bordes
imshow("Edges", edges);
if (waitKey(30) == 27) {
break;
}
}
cap.release();
destroyAllWindows();
Técnicas avanzadas de procesamiento de video
Sustracción de fondo de video
La sustracción de fondo se utiliza para extraer objetos en primer plano del video.
Ejemplo
#include <iostream>
using namespace cv;
using namespace std;
int main() {
// Abrir archivo de video o cámara
VideoCapture cap("video.mp4");
if (!cap.isOpened()) {
cout << "Error: ¡No se puede abrir el archivo de video o la cámara!" << endl;
return -1;
}
// Crear el sustractor de fondo
Ptr<BackgroundSubtractor> bgSubtractor = createBackgroundSubtractorMOG2();
// Procesar fotogramas de video
Mat frame, fgMask;
while (true) {
cap >> frame;
if (frame.empty()) break;
// Aplicar sustracción de fondo
bgSubtractor->apply(frame, fgMask);
// Mostrar el resultado
imshow("Frame", frame);
imshow("Foreground Mask", fgMask);
// Presionar la tecla ESC para salir
if (waitKey(30) == 27) break;
}
// Liberar recursos
cap.release();
destroyAllWindows();
return 0;
}
Cálculo de flujo óptico
El flujo óptico se utiliza para calcular el movimiento de objetos en los fotogramas de video.
Flujo óptico disperso (método Lucas-Kanade):
Ejemplo
#include <iostream>
using namespace cv;
using namespace std;
int main() {
// Abrir archivo de video o cámara
VideoCapture cap("video.mp4");
if (!cap.isOpened()) {
cout << "Error: ¡No se puede abrir el archivo de video o la cámara!" << endl;
return -1;
}
// Leer el primer fotograma
Mat oldFrame, oldGray;
cap >> oldFrame;
cvtColor(oldFrame, oldGray, COLOR_BGR2GRAY);
// Seleccionar puntos de características
vector<Point2f> oldPoints;
goodFeaturesToTrack(oldGray, oldPoints, 100, 0.3, 7);
// Procesar fotogramas de video
Mat frame, gray;
while (true) {
cap >> frame;
if (frame.empty()) break;
// Convertir a imagen en escala de grises
cvtColor(frame, gray, COLOR_BGR2GRAY);
// Calcular el flujo óptico
vector<Point2f> newPoints;
vector<uchar> status;
vector<float> err;
calcOpticalFlowPyrLK(oldGray, gray, oldPoints, newPoints, status, err);
// Dibujar trayectorias de flujo óptico
for (size_t i = 0; i < oldPoints.size(); i++) {
if (status[i]) {
line(frame, oldPoints[i], newPoints[i], Scalar(0, 255, 0), 2);
circle(frame, newPoints[i], 3, Scalar(0, 0, 255), -1);
}
}
// Actualizar fotograma y puntos de características
oldGray = gray.clone();
oldPoints = newPoints;
// Mostrar el resultado
imshow("Optical Flow", frame);
// Presionar la tecla ESC para salir
if (waitKey(30) == 27) break;
}
// Liberar recursos
cap.release();
destroyAllWindows();
return 0;
}