Обработка видео на C++ OpenCV

Обработка видео означает обработку и анализ каждого кадра видеопоследовательности.

OpenCV предоставляет мощные инструменты для обработки видеоданных, включая чтение видео, обработку кадров, сохранение видео и обработку видео в реальном времени.

Сценарии применения обработки видео

Видеонаблюдение:

  • Используйте вычитание фона для обнаружения движущихся объектов.

  • Используйте оптический поток для анализа траекторий движения объектов.

Анализ видео:

  • Извлекайте ключевые кадры из видео.

  • Анализируйте поведение объектов в видео.

Обработка в реальном времени:

  • Видеофильтры в реальном времени (например, обнаружение границ, размытие и т. д.).

  • Обнаружение и отслеживание объектов в реальном времени.


Чтение и отображение видео

Чтение видеофайлов (VideoCapture)

В OpenCV,VideoCaptureкласс используется для чтения видеокадров из видеофайлов или с камер.

Чтобы прочитать видеофайл, сначала создайтеVideoCaptureобъект и укажите путь к видеофайлу.

Пример

#include <opencv2/opencv.hpp>
using namespace cv;

int main() {
    // Создайте объект VideoCapture и откройте видеофайл
    VideoCapture cap("example.mp4");

    // Проверьте, успешно ли открылось видео
    if (!cap.isOpened()) {
        std::cerr << "Ошибка: не удалось открыть видеофайл." << std::endl;
        return -1;
    }

    // Код чтения и отображения видео будет представлен ниже
    return 0;
}

Отображение видеокадров

После чтения видеофайла вы можете считывать видео кадр за кадром в цикле и использоватьimshowфункцию для отображения каждого кадра.

Пример

Mat frame;
while (true) {
    // Считать следующий кадр
    cap >> frame;

    // Если кадр пуст, видео закончилось
    if (frame.empty()) {
        break;
    }

    // Отобразить текущий кадр
    imshow("Video", frame);

    // Подождать 30 миллисекунд, нажмите ESC для выхода
    if (waitKey(30) == 27) {
        break;
    }
}

// Освободить объект VideoCapture
cap.release();
// Закрыть все окна
destroyAllWindows();

Сохранение видео (VideoWriter)

Если вы хотите сохранить обработанное видео в файл, можно использоватьVideoWriterкласс. Сначала нужно указать выходной файл, формат кодирования, частоту кадров и размер кадра.

Пример

// Получить частоту кадров и размер кадра видео
double fps = cap.get(CAP_PROP_FPS);
Size frameSize(cap.get(CAP_PROP_FRAME_WIDTH), cap.get(CAP_PROP_FRAME_HEIGHT));

// Создать объект VideoWriter
VideoWriter writer("output.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), fps, frameSize);

while (true) {
    cap >> frame;
    if (frame.empty()) {
        break;
    }

    // Записать кадры в выходной видеофайл
    writer.write(frame);

    imshow("Video", frame);
    if (waitKey(30) == 27) {
        break;
    }
}

// Освободить объекты VideoCapture и VideoWriter
cap.release();
writer.release();
destroyAllWindows();

Обработка видеокадров

Покадровая обработка видео

При обработке видео обычно необходимо выполнять определённые операции обработки над каждым кадром. Например, можно преобразовать каждый кадр в оттенки серого, выполнить обнаружение краёв и т. д.

Пример

while (true) {
    cap >> frame;
    if (frame.empty()) {
        break;
    }

    // Преобразовать кадр в изображение в оттенках серого
    Mat grayFrame;
    cvtColor(frame, grayFrame, COLOR_BGR2GRAY);

    // Отобразить кадр в оттенках серого
    imshow("Серое видео", grayFrame);

    if (waitKey(30) == 27) {
        break;
    }
}

Обработка видеокадров в реальном времени

При обработке видеокадров в реальном времени обычно необходимо применять к каждому кадру некоторые алгоритмы обработки в реальном времени. Например, обнаруживать движущиеся объекты в видео в реальном времени.

Пример

Mat prevFrame, nextFrame, diffFrame;
cap >> prevFrame;
cvtColor(prevFrame, prevFrame, COLOR_BGR2GRAY);

while (true) {
    cap >> nextFrame;
    if (nextFrame.empty()) {
        break;
    }

    cvtColor(nextFrame, nextFrame, COLOR_BGR2GRAY);

    // Вычислить разницу между кадрами
    absdiff(prevFrame, nextFrame, diffFrame);

    // Отобразить разностный кадр
    imshow("Обнаружение движения", diffFrame);

    // Обновить предыдущий кадр
    prevFrame = nextFrame.clone();

    if (waitKey(30) == 27) {
        break;
    }
}

Обработка камеры в реальном времени

Открытие камеры

ИспользуяVideoCaptureкласс, вы можете не только читать видеофайлы, но и открывать камеру для обработки видеопотока в реальном времени. Чтобы открыть камеру, просто установитеVideoCaptureпараметр в 0 (что указывает на камеру по умолчанию).

Пример

VideoCapture cap(0);

if (!cap.isOpened()) {
    std::cerr << "Error: Could not open camera." << std::endl;
    return -1;
}

Обработка видеопотоков в реальном времени

После открытия камеры вы можете обрабатывать видеопоток в реальном времени покадрово, так же, как и видеофайл. Например, вы можете применить алгоритм обнаружения границ к видеопотоку в реальном времени.

Пример

while (true) {
    cap >> frame;
    if (frame.empty()) {
        break;
    }

    // Применить обнаружение границ Canny
    Mat edges;
    Canny(frame, edges, 100, 200);

    // Отобразить результат обнаружения границ
    imshow("Края", edges);

    if (waitKey(30) == 27) {
        break;
    }
}

cap.release();
destroyAllWindows();

Продвинутые методы обработки видео

Вычитание фона в видео

Вычитание фона используется для извлечения объектов переднего плана из видео.

Пример

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    // Открыть видеофайл или камеру
    VideoCapture cap("video.mp4");
    if (!cap.isOpened()) {
        cout << "Ошибка: не удалось открыть видеофайл или камеру!" << endl;
        return -1;
    }

    // Создать вычитатель фона
    Ptr<BackgroundSubtractor> bgSubtractor = createBackgroundSubtractorMOG2();

    // Обработать кадры видео
    Mat frame, fgMask;
    while (true) {
        cap >> frame;
        if (frame.empty()) break;

        // Применить вычитание фона
        bgSubtractor->apply(frame, fgMask);

        // Вывести результат
        imshow("Кадр", frame);
        imshow("Маска переднего плана", fgMask);

        // Нажмите ESC для выхода
        if (waitKey(30) == 27) break;
    }

    // Освободить ресурсы
    cap.release();
    destroyAllWindows();

    return 0;
}

Вычисление оптического потока

Оптический поток используется для вычисления движения объектов в видеокадрах.

Разреженный оптический поток (метод Лукаса — Канаде):

Пример

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    // Открыть видеофайл или камеру
    VideoCapture cap("video.mp4");
    if (!cap.isOpened()) {
        cout << "Ошибка: не удалось открыть видеофайл или камеру!" << endl;
        return -1;
    }

    // Прочитать первый кадр
    Mat oldFrame, oldGray;
    cap >> oldFrame;
    cvtColor(oldFrame, oldGray, COLOR_BGR2GRAY);

    // Выбрать особые точки
    vector<Point2f> oldPoints;
    goodFeaturesToTrack(oldGray, oldPoints, 100, 0.3, 7);

    // Обработать кадры видео
    Mat frame, gray;
    while (true) {
        cap >> frame;
        if (frame.empty()) break;

        // Преобразовать в оттенки серого
        cvtColor(frame, gray, COLOR_BGR2GRAY);

        // Вычислить оптический поток
        vector<Point2f> newPoints;
        vector<uchar> status;
        vector<float> err;
        calcOpticalFlowPyrLK(oldGray, gray, oldPoints, newPoints, status, err);

        // Нарисовать траектории оптического потока
        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);
            }
        }

        // Обновить кадры и характерные точки
        oldGray = gray.clone();
        oldPoints = newPoints;

        // Вывести результат
        imshow("Оптический поток", frame);

        // Нажмите ESC для выхода
        if (waitKey(30) == 27) break;
    }

    // Освободить ресурсы
    cap.release();
    destroyAllWindows();

    return 0;
}
Другие расширения