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í: