Processamento de Vídeo
Este relatório documenta o Laboratório 5 — Experimentos de Subtração de Fundo — da disciplina de Processamento de Vídeo. O objetivo deste trabalho é estudar métodos de detecção de movimento e segmentação de primeiro-plano através de subtração de fundo, comparar algoritmos e avaliar o impacto de parâmetros práticos em vídeos reais.
O processamento de vídeo e imagem se baseia na manipulação de dados em formato de matriz, sendo a biblioteca OpenCV a ferramenta central, responsável por fornecer as rotinas de Entrada/Saída.
No OpenCV, uma imagem estática é carregada como uma matriz NumPy, onde cada elemento é um pixel de cor, sendo o padrão de canais o BGR (Azul, Verde, Vermelho).
Já o vídeo é tratado como uma sequência de imagens estáticas, chamadas de frames, que são processadas individualmente em um loop através do objeto `cv2.VideoCapture` e exibidas na tela a uma taxa de FPS (Frames por Segundo), métrica fundamental para a avaliação do desempenho de qualquer algoritmo de processamento em tempo real.
O que é: Uma distribuição Linux de código aberto.
Finalidade: Fornece o sistema operacional e o ambiente de desenvolvimento onde todas as ferramentas serão instaladas e executadas.
O que é: Interface de linha de comando (CLI).
Finalidade: Utilizado para executar comandos do sistema, gerenciar ambientes, instalar softwares e rodar programas.
O que é: Miniconda é um gerenciador de pacotes e ambientes leve para Python.
Finalidade:
O que é: Biblioteca de Visão Computacional de Código Aberto.
Finalidade: Principal biblioteca usada para tarefas de visão computacional e processamento de imagens/vídeos (detecção de objetos, transformações, extração de características etc.).
Variantes:
Essenciais para compilar e executar o OpenCV a partir do código-fonte:
O que é: Ferramenta auxiliar para configurar flags de compilação e linkagem de bibliotecas.
Finalidade: Verifica se o OpenCV está instalado e acessível (pkg-config --modversion opencv4).
O que sao: Linguagens de programação usadas para rodar os scripts com OpenCV.
Finalidade: Fornece o ambiente de programação para desenvolver tarefas de visão computacional.
O que é: Reprodutor multimídia gratuito e de código aberto.
Finalidade: Permite visualizar vídeos e imagens fora do OpenCV, útil para testes e validação de resultados do processamento de vídeo.
Desenvolvimento de programa para gravação utilizando cv2.VideoWriter
Objetivo: Registrar e salvar transmissões para análise posterior.
O vídeo capturado foi salvo no formato .avi, com qualidade satisfatória e sincronização estável entre captura e gravação.
Este laboratório explora técnicas de subtração de fundo usando OpenCV (MOG2, KNN). O código de
apoio e instruções estão disponíveis na pasta ../lab5/.
Arquivos principais:
g++ -std=c++17 ../lab5/bg_sub_custom.cpp -o bg_sub_custom `pkg-config --cflags --libs opencv4`
./bg_sub_custom ../lab5/vtest.avi fast — rodar com vídeo de teste (modo rápido)
./bg_sub_custom ../lab5/vtest.avi slow — rodar com modo mais preciso/lento./bg_sub_custom 0 fast — usar webcam (0) em modo rápidoCopie o código abaixo para bg_sub_custom.cpp ou abra o arquivo em ../lab5/.
#include <opencv2/opencv.hpp>
#include <iostream>
#include <string>
#include <filesystem>
using namespace cv;
using std::cout;
using std::cerr;
using std::endl;
using std::string;
struct Config {
int min_brightness;
int max_brightness;
int min_area;
double learning_rate;
int bg_thresh;
Size morph_kernel;
};
int main(int argc, char** argv)
{
if (argc < 3) {
cerr << "Usage: " << argv[0] << " <video_path> <mode: fast|slow>" << endl;
return 1;
}
string video_path = argv[1];
string mode = argv[2];
Config cfg;
if (mode == "fast") {
cfg.min_brightness = 30;
cfg.max_brightness = 220;
cfg.min_area = 800;
cfg.learning_rate = 0.7; // fast adaptation
cfg.bg_thresh = 900;
cfg.morph_kernel = Size(3,3);
} else if (mode == "slow") {
cfg.min_brightness = 40;
cfg.max_brightness = 180;
cfg.min_area = 1200;
cfg.learning_rate = 0.05; // slow adaptation
cfg.bg_thresh = 300;
cfg.morph_kernel = Size(7,7);
} else {
cerr << "Mode must be 'fast' or 'slow'" << endl;
return 1;
}
VideoCapture cap(video_path);
if (!cap.isOpened()) {
cerr << "❌ Cannot open video: " << video_path << endl;
return 1;
}
int frame_width = static_cast<int>(cap.get(CAP_PROP_FRAME_WIDTH));
int frame_height = static_cast<int>(cap.get(CAP_PROP_FRAME_HEIGHT));
double fps = cap.get(CAP_PROP_FPS);
if (fps <= 0.0) fps = 20.0;
Size frame_size(frame_width, frame_height);
// ensure outputs directory
std::filesystem::create_directories("./outputs");
string output_path = "./outputs/" + mode + "_output_video.avi";
int fourcc = VideoWriter::fourcc('M','J','P','G');
VideoWriter writer(output_path, fourcc, fps, frame_size);
if (!writer.isOpened()) {
cerr << "Could not open output writer: " << output_path << endl;
// continue, we can still show windows
}
Ptr<BackgroundSubtractorKNN> backSub = createBackgroundSubtractorKNN(false);
backSub->setDist2Threshold(cfg.bg_thresh);
cout << "▶ Processing " << mode << " mode... Press 'q' to quit" << endl;
Mat frame, gray, mask, gray_masked, fgmask;
Mat kernel = getStructuringElement(MORPH_ELLIPSE, cfg.morph_kernel);
while (true) {
if (!cap.read(frame) || frame.empty())
break;
// convert to grayscale
cvtColor(frame, gray, COLOR_BGR2GRAY);
// brightness mask
inRange(gray, Scalar(cfg.min_brightness), Scalar(cfg.max_brightness), mask);
bitwise_and(gray, gray, gray_masked, mask);
// apply background subtraction on masked grayscale
backSub->apply(gray_masked, fgmask, cfg.learning_rate);
// morphological cleanup (erode then dilate)
erode(fgmask, fgmask, kernel, Point(-1,-1), 1);
dilate(fgmask, fgmask, kernel, Point(-1,-1), 2);
// find contours
std::vector<std::vector<Point>> contours;
std::vector<Vec4i> hierarchy;
findContours(fgmask, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
Mat result = frame.clone();
for (const auto &cont : contours) {
double area = contourArea(cont);
if (area < cfg.min_area) continue;
Rect r = boundingRect(cont);
rectangle(result, r, Scalar(0,255,0), 2);
putText(result, std::to_string(static_cast<int>(area)), Point(r.x, r.y-10), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0,255,0), 2);
}
// write FG mask as 3-channel for video output (if writer opened)
if (writer.isOpened()) {
Mat fg_bgr;
cvtColor(fgmask, fg_bgr, COLOR_GRAY2BGR);
writer.write(fg_bgr);
}
// display
imshow("Motion Detection (" + mode + ")", fgmask);
imshow("Result (" + mode + ")", result);
char c = static_cast<char>(waitKey(30));
if (c == 'q' || c == 27)
break;
}
cap.release();
if (writer.isOpened()) writer.release();
destroyAllWindows();
cout << "✅ Output saved to " << output_path << endl;
return 0;
}
vtest.avi, baixe-o no
repositório OpenCV ou utilize um arquivo de vídeo próprio. Verifique também se o
pkg-config encontra opencv4 na sua máquina.
O experimento permitiu compreender de forma prática os fundamentos da captura, exibição e gravação de imagens e vídeos com OpenCV.
A subtração de fundo é uma família de métodos que modelam o fundo da cena e extraem o primeiro-plano em movimento. No OpenCV, as implementações mais utilizadas são MOG2 e KNN. Ambos constroem um modelo por pixel ao longo do tempo e classificam cada novo pixel como fundo ou primeiro-plano com base nesse modelo.
Principais pontos: inicialização do modelo, atualização contínua (taxa de aprendizado) e limiar para decidir se um pixel diverge do fundo.
Qualquer pipeline de detecção depende fortemente da qualidade das imagens: exposição, balanço de branco, ruído, resolução e compressão alteram significativamente os resultados. Pré-processamentos úteis:
Breve comparação técnica:
Escolha prática: MOG2 costuma lidar melhor com fundos multimodais; KNN pode ser mais estável em cenários com ruído periódico.
Durante os experimentos observamos problemas comuns e formas de mitigá-los:
Que aplicações práticas são possíveis com subtração de fundo e detecção de movimento?
As técnicas de subtração de fundo e detecção de movimento têm ampla aplicação prática. Exemplos:
Conclusão curta: background subtraction + motion detection são blocos construtivos para muitas aplicações reais — vigilância, contagem, análise de tráfego e automação - fornece evidências práticas sobre sensibilidade, robustez e desempenho para escolher a configuração adequada.