OpenCV 3.1 (C++) sobre Qt 5 en Linux – Texto en video

OpenCV 3.1 (C++) sobre Qt 5 en Linux – Texto en video

OpenCV (Open Source Computer Vision) es un excelente conjunto de herramientas para la visión artificial. También ofrece una forma sencilla de capturar secuencias de video desde dispositivos externos, como una cámara. En este tutorial se introducirá OpenCV y se mostrará un método para la captura de video desde una cámara web o desde un archivo de video, desplegando un texto en tiempo real sobre el video, todo esto en conjunto con Qt.

Para la instalación y configuración de OpenCV 3.1 y Qt en Debian 8 Linux, les recomiendo la guía que desarrollé hace un tiempo: OpenCV 3.1 con CUDA 7.5 sobre Qt 5 en Debian 8 (pueden omitir la instalación de CUDA si su GPU no es soportada).


Descripción del proyecto

El proyecto consiste en visualizar un texto obtenido desde un QLineEdit o un campo de entrada de texto sobre un video pregrabado o capturado en tiempo real desde la webcam del notebook o PC.


Diagrama de flujo simplificado

Diagrama de flujo del proyecto.


Creación del proyecto

Seleccionamos crear un nuevo proyecto.

Creación de un nuevo proyecto Qt 5

Configuramos el archivo .pro agregando las librerías necesarias para el correcto funcionamiento de OpenCV:

INCLUDEPATH += /usr/local/include/opencv-3.1.0  
LIBS += `pkg-config opencv --libs --cflags`

En mi caso, el archivo TextoEnVideo-OpenCV.pro queda de la siguiente forma:

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = TextoEnVideo-OpenCV  
TEMPLATE = app

INCLUDEPATH += /usr/local/include/opencv-3.1.0  
LIBS += `pkg-config opencv --libs --cflags`

SOURCES += main.cpp \
           mainwindow.cpp

HEADERS += mainwindow.h

FORMS   += mainwindow.ui

Headers

Agregamos los headers de OpenCV y QFileDialog (para poder utilizar el selector de archivos) en el archivo mainwindow.h:

#include <QFileDialog>

#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

Interfaz de usuario (UI)

El diseño queda a criterio del usuario. No obstante, como mínimo, la aplicación debe contar con dos botones: uno configurado como checkable para las opciones de reproducir y detener, y otro para seleccionar el archivo de video, además de radio buttons para identificar la fuente del video.

Se deja el código fuente completo en caso de que surjan dudas.

Qt OpenCV – Texto en video


Código de las funciones principales

Se omitieron los namespaces con fines académicos, de modo que el lector pueda identificar claramente a qué clase corresponde cada método.

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget* parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

/**
 * Método para obtener la dirección del video
 * @brief MainWindow::SeleccionarVideo
 */
void MainWindow::SeleccionarVideo()
{
    // Declara la variable con la ruta del archivo
    QString archivo = QFileDialog::getOpenFileName(this,
        tr("Abrir video"),
        "",
        tr("Videos (*.avi *.mp4 *.mov)"));

    // Agrega la ruta del archivo
    ui->labelVideo->setText(archivo);
    ui->radioVideo->setChecked(true);
}

/**
 * Método para procesar el video frame a frame si checked == true
 * @brief MainWindow::ProcesarVideo
 * @param checked
 */
void MainWindow::ProcesarVideo(bool checked)
{
    cv::destroyAllWindows(); // Cierra todas las ventanas

    cv::Mat frame; // Frame como arreglo multidimensional

    if (!checked) { // Si no está checked, detiene el video
        ui->play->setText("Iniciar video");
        cap.release();
    }
    else {
        ui->play->setText("Parar video");

        if (ui->radioVideo->isChecked()) { // Reproduce video desde archivo
            cap.open(ui->labelVideo->text().toStdString().c_str());
        }
        else { // Usa la webcam
            cap.open(0);
        }
    }

    while (checked) // Bucle hasta que se presione "Parar video"
    {
        cap >> frame; // Obtiene un nuevo frame del video o cámara
        if (frame.empty())
            break; // Detiene el bucle si el frame está vacío

        // Insertamos el texto en el video
        cv::putText(frame,
            ui->lineTexto->text().toStdString(),
            cv::Point(20, 60),
            cv::FONT_HERSHEY_TRIPLEX,
            2,
            cv::Scalar(255, 255, 255),
            4);

        cv::namedWindow("Reproductor", cv::WINDOW_KEEPRATIO);
        cv::imshow("Reproductor", frame);

        char key = (char)cv::waitKey(20); // Espera 20 ms por la tecla ESC
        if (key == 27)
            break;
    }
}

void MainWindow::on_toolButton_clicked()
{
    SeleccionarVideo();
}

void MainWindow::on_actionAbrir_Video_triggered()
{
    SeleccionarVideo();
}

void MainWindow::on_play_toggled(bool checked)
{
    ProcesarVideo(checked);
}

Cada método debe estar previamente definido en los headers. Para mayor detalle, puede descargar el código fuente completo disponible aquí:

Descargar código en GitHub – Qt OpenCV Texto en video