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

#include <opencv2/opencv.hpp>
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

Mat frame;
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

// Obtener la velocidad de fotogramas y el tamaño del fotograma del video
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

while (true) {
    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

Mat prevFrame, nextFrame, diffFrame;
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

VideoCapture cap(0);

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

while (true) {
    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 <opencv2/opencv.hpp>
#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 <opencv2/opencv.hpp>
#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;
}
Otras extensiones