Desarrollo C/C++, opencv y qt combinados para reproducir vídeos.

Tabla de contenido

1. creación de qt_ui

        1.1 configuración de interfaz de usuario

         1.2 Guardar interfaz de usuario y salida de código

2. Crear proyecto

        2.1 Directorio del proyecto y configuración de compilación

        2.2 Diseño del código fuente

3. Compilación y prueba.

        3.1 Compilación del programa

        3.2 Programa en ejecución


        En primer lugar, permítanme decirles que este es un caso del documento de aprendizaje de OpenCV 3, pero la descripción está un poco omitida, solo hay algunas descripciones de código breves, lo grabaré y lo compartiré con todos durante el proceso de aprendizaje y verificación. .

1. creación de qt_ui

        1.1 configuración de interfaz de usuario

        Este artículo utiliza la versión qt5.8_msvc2015_64.

        Ingrese al directorio bin de qt y abra la herramienta de diseño qt_ui designer.exe

         Cree un formulario de widget, el objeto QWidget, denominado QMoviePlayer.

         Luego cree un objeto QFrame llamado marco. Este objeto se puede usar para abrir un cuadro de visualización de relación de aspecto adecuada en el formulario QMoviePlayer. Este cuadro de visualización se usa para mostrar videos.

         Después de completar la configuración, guarde la interfaz de usuario, por ejemplo QMoviePlayer.ui

         1.2 Guardar interfaz de usuario y salida de código

        El contenido xml de mi archivo QMoviePlayer.ui es el siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>QMoviePlayer</class>
 <widget class="QWidget" name="QMoviePlayer">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>600</width>
    <height>303</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <widget class="QFrame" name="frame">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>601</width>
     <height>241</height>
    </rect>
   </property>
   <property name="frameShape">
    <enum>QFrame::StyledPanel</enum>
   </property>
   <property name="frameShadow">
    <enum>QFrame::Raised</enum>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

        Haga clic en el menú del formulario, ingrese Ver código, guarde el archivo de código como ui_QMoviePlayer.h o cree un nuevo archivo de encabezado y copie el contenido directamente en el archivo de encabezado y guárdelo.

         El contenido del código de mi ui_QMoviePlayer.h es el siguiente.

/********************************************************************************
** Form generated from reading UI file 'QMoviePlayerp15136.ui'
**
** Created by: Qt User Interface Compiler version 5.8.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/

#ifndef QMOVIEPLAYERP15136_H
#define QMOVIEPLAYERP15136_H

#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QFrame>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QWidget>

QT_BEGIN_NAMESPACE

class Ui_QMoviePlayer
{
public:
    QFrame *frame;

    void setupUi(QWidget *QMoviePlayer)
    {
        if (QMoviePlayer->objectName().isEmpty())
            QMoviePlayer->setObjectName(QStringLiteral("QMoviePlayer"));
        QMoviePlayer->resize(600, 303);
        frame = new QFrame(QMoviePlayer);
        frame->setObjectName(QStringLiteral("frame"));
        frame->setGeometry(QRect(0, 0, 601, 241));
        frame->setFrameShape(QFrame::StyledPanel);
        frame->setFrameShadow(QFrame::Raised);

        retranslateUi(QMoviePlayer);

        QMetaObject::connectSlotsByName(QMoviePlayer);
    } // setupUi

    void retranslateUi(QWidget *QMoviePlayer)
    {
        QMoviePlayer->setWindowTitle(QApplication::translate("QMoviePlayer", "Form", Q_NULLPTR));
    } // retranslateUi

};

namespace Ui {
    class QMoviePlayer: public Ui_QMoviePlayer {};
} // namespace Ui

QT_END_NAMESPACE

#endif // QMOVIEPLAYERP15136_H

2. Crear proyecto

        2.1 Directorio del proyecto y configuración de compilación

        Cree un archivo de proyecto en el directorio opencv_qt, la organización del proyecto es la siguiente:

opencv_qt
    bin
    build_vc
    src
        main.cpp
        ui_QMoviePlayer.h
        QMoviePlayer.h
        QMoviePlayer.cpp
        QMoviePlayer.ui
    CMakeLists.txt      #cmake工程
    vcbuild_2015.bat    #编译命令

        ui_QMoviePlayer.h y QMoviePlayer.ui son los archivos de encabezado de código y de interfaz de usuario implementados previamente con Designer.exe.

        El contenido del archivo CMakeLists.txt es el siguiente. Hay rastros de win/linux en este artículo. Sin embargo, este artículo solo implementa el método de compilación win basado en vc2015 + qt_vc2015 + opencv_vc. Este artículo no ha sido probado en Linux. Los lectores interesados ​​pueden hacer clic en este módulo Implementación de soporte de ajuste (para casos de llamada y compilación de la biblioteca opencv Linux, consulte otras publicaciones de blog en esta columna). El enlace qt utiliza una biblioteca dinámica. La biblioteca opencv compilada en base a vc2015 está precompilada en este artículo ( Desarrollo de C/C++, instalación de opencv y aplicación bajo instalación win_c++ opencv Library_py_free-IoT Intelligent Blog-CSDN Blog ).

# CMake 最低版本号要求
cmake_minimum_required (VERSION 3.1.0)
# 项目信息
set(proname "opencv_qt")
project(${proname} VERSION 1.0.0 LANGUAGES CXX)

if(WIN32)
    message(STATUS "windows compiling...")
	set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
	set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
    add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
    add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
    add_definitions(
        -D_PLATFORM_IS_WINDOWS_
        -D_CRT_SECURE_NO_WARNINGS
        -D_WINSOCK_DEPRECATED_NO_WARNINGS
        # -DZLIB_WINAPI
        -DUNICODE
        -D_UNICODE
        # -DQT_DLL
        # -DQT_CORE_LIB
        # -DQT_GUI_LIB
        # -DQT_WIDGETS_LIB
        # -D CMAKE_CXX_FLAGS="/utf-8"
    )

else(WIN32)
    message(STATUS "linux compiling...")
    # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -I/usr/include -L/lib/x86_64-linux-gnu -lpthread -pthread -lm -lrt -ldl -lz -luuid ")  #qt需要-fPIC编译指定
    add_definitions(
        -D_PLATFORM_IS_LINUX_
        "-g"
        # "-std=gnu++0x"
        "-std=c++11"
        "-O2"
        # "-pipe"
        "-Wno-invalid-source-encoding"
        "-Wdeprecated-declarations"
        "-W"
        "-fPIC"
        "-Wall"
        # "-Werror"
        # "-Wshadow"
        # "-Wformat"
        # "-Wpointer-arith"
        "-D_REENTRANT"
        # "-D_USE_FAST_MACRO"
        # "-Wno-long-long"
        # "-Wuninitialized"
        # "-D_POSIX_PTHREAD_SEMANTICS"
        # "-Wno-unused-parameter"
        "-fexceptions"
        "-DQT_NO_DEBUG"
        "-DDQT_QML_DEBUG"
    )
endif(WIN32)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

if(CMAKE_VERSION VERSION_LESS "3.7.0")
    set(CMAKE_INCLUDE_CURRENT_DIR ON)
endif()

set(EXECUTABLE_OUTPUT_PATH   ${PROJECT_SOURCE_DIR}/bin)
# 创建 EXECUTABLE_OUTPUT_PATH 指向的文件夹
execute_process( COMMAND ${CMAKE_COMMAND} -E make_directory ${EXECUTABLE_OUTPUT_PATH})

set(PROJECT_CUR_DIR .)

if(WIN32)
set(QTDIR "D:/workForSoftware/Qt/Qt5.8.0/5.8/msvc2015_64")
else(WIN32)
set(QTDIR "/opt/qt-5.8_static")
endif(WIN32)
message("QTDIR = ${QTDIR}")
set(Qt5_DIR "${QTDIR}/lib/cmake/Qt5")
message("Qt5_DIR  = ${Qt5_DIR}")

set(CMAKE_AUTOMOC ON)
# set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
#查找需要的Qt库文件,最好每一个库都要写,Qt也会根据依赖关系自动添加
find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED)
cmake_policy(SET CMP0020 NEW)

set(CMAKE_INCLUDE_CURRENT_DIR ON) #包含编译目录

FILE(GLOB srcfile ${PROJECT_CUR_DIR}/src/*.h ${PROJECT_CUR_DIR}/src/*.cpp )             #加载文件夹下的所有源码文件
LIST(APPEND code_file ${srcfile} ) #变量合并

include_directories(
    "${PROJECT_CUR_DIR}"
    "${PROJECT_CUR_DIR}/src"
    "${PROJECT_CUR_DIR}/../../opencv_vc/include"
    "${QTDIR}/include"
    "${QTDIR}/include/QtCore"
    "${QTDIR}/include/QtGui"
    "${QTDIR}/include/QtWidgets"
)

#link 目录
link_directories(
    "${QTDIR}/lib"
    "${PROJECT_CUR_DIR}/../../opencv_VC/x64/vc14/lib"
)

message("RESOURCES = ${RESOURCES}")

add_executable(${proname}  ${code_file} ${RESOURCES} ${RC_FILE} )

# 链接指定
set(link_lib 
    Qt5::Core Qt5::Gui Qt5::Widgets
)
if(WIN32)
if (CMAKE_BUILD_TYPE STREQUAL "release")
set(link_lib_opencv 
    opencv_img_hash460.lib opencv_world460.lib
)
else()
set(link_lib_opencv 
    opencv_img_hash460d.lib opencv_world460d.lib
)
endif()
endif(WIN32)

target_link_libraries(${proname} 
    ${link_lib}
    ${link_lib_opencv}
)

#去除 CMD 窗口
if(WIN32)
message("CMAKE_BUILD_TYPE =${CMAKE_BUILD_TYPE}")
if (CMAKE_BUILD_TYPE STREQUAL "release")
if(MSVC)
    set_target_properties(${proname} PROPERTIES
        WIN32_EXECUTABLE YES
        LINK_FLAGS "/ENTRY:mainCRTStartup"
    )
elseif(CMAKE_COMPILER_IS_GNUCXX)
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mwindows") # Not tested
else()
    message(SEND_ERROR "You are using an unsupported Windows compiler! (Not MSVC or GCC)")
endif(MSVC)
endif()

endif(WIN32)

        vcbuild_2015.bat es un script creado para facilitar la compilación. Los lectores también pueden compilar manualmente de acuerdo con el comando del script.

md build_vc
cd ./build_vc
@REM 单独编译时可能需要独立设置环境变量
if [%vccompilerversion%] EQU  [] ( set vccompilerversion="Visual Studio 14 2015 Win64" )

@REM 工程配置
cmake -G %vccompilerversion% .. -DCMAKE_BUILD_TYPE=debug
@REM 编译
cmake --build . --config debug

@REM 工程配置
cmake -G %vccompilerversion% .. -DCMAKE_BUILD_TYPE=release
@REM 编译
cmake --build . --config release

cd ..

        2.2 Diseño del código fuente

        Echemos un vistazo a cómo el código fuente implementa la lectura y reproducción de videos.

        El contenido de QMoviePlayer.h es el siguiente. Este archivo de encabezado define un tipo de ventana. La parte de visualización de la ventana proviene del diseño de interfaz de usuario anterior "Ui::QMoviePlayer ui" y define "cv::VideoCapture m_cap" para capturar contenido de video:

#ifndef _QMOVIEPLAYER_H_
#define _QMOVIEPLAYER_H_

#include "ui_QMoviePlayer.h"
#include <QtWidgets/QWidget>
#include <QImage>

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

QT_BEGIN_NAMESPACE
class QPaintEvent;
class QTimer;
QT_END_NAMESPACE

class QMoviePlayer : public QWidget 
{
    Q_OBJECT
    public:
        QMoviePlayer(QWidget *parent = NULL);
        virtual ~QMoviePlayer(){;}
        bool open( string file );
    public slots:
        void nextFrame();

    private:
        void paintEvent( QPaintEvent* q);
        void _copyImage( void);
    private:
        Ui::QMoviePlayer ui;    //ui界面
        cv::VideoCapture m_cap; //opencv的视频读取及捕获图像实现
        QImage m_qt_img;
        cv::Mat m_cv_img;       //图像缓存矩阵
        QTimer* m_timer;
};

#endif //_QMOVIEPLAYER_H_

        El contenido de QMoviePlayer.cpp es el siguiente. La función abrir se usa para abrir un archivo de video y leer periódicamente los datos de la imagen del cuadro a través del objeto QTimer. nextFrame se usa para leer los datos de la imagen y actualizarlos en la visualización de la ventana; la función _copyImage es La clave para combinar opencv y QT convierte la imagen m_cv_img capturada por opencv en la imagen m_qt_img de qt, de modo que la imagen se pueda actualizar en la ventana en modo qt:

#include "QMoviePlayer.h"

#include <QPainter>
#include <QTimer>

QMoviePlayer::QMoviePlayer(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi( this );
}

bool QMoviePlayer::open( string file)
{
    if( !m_cap.open( file)) return false;
    // If we opened the file, set up everything now:
    //
    m_cap.read( m_cv_img );
    m_qt_img = QImage(
        QSize( m_cv_img.cols,m_cv_img.rows),
        QImage::Format_RGB888
    );
    ui.frame->setMinimumSize( m_qt_img.width(),m_qt_img.height());
    ui.frame->setMaximumSize( m_qt_img.width(),m_qt_img.height());
    _copyImage();

    m_timer = new QTimer( this );
    connect(m_timer, SIGNAL( timeout()), this, SLOT( nextFrame()) );
    m_timer->start( 1000.0 / m_cap.get( cv::CAP_PROP_FPS));
    return true;
}

void QMoviePlayer::nextFrame()
{
    // Nothing to do if capture object is not open
    //
    if( !m_cap.isOpened()) return;
    m_cap.read(m_cv_img);
    if(m_cv_img.empty()) return;
    _copyImage();
    this->update();
}

void QMoviePlayer::paintEvent( QPaintEvent* e )
{
    QPainter painter( this );
    painter.drawImage( QPoint( ui.frame->x(),ui.frame->y()),m_qt_img);
}

void QMoviePlayer::_copyImage( void)
{
    // Copy the image data into the Qt QImage
    //
    cv::Mat cv_header_to_qt_image(
        cv::Size(
            m_qt_img.width(),
            m_qt_img.height()
        ),
        CV_8UC3,
        m_qt_img.bits()
    );
    cv::cvtColor(m_cv_img,cv_header_to_qt_image, cv::COLOR_BGR2RGB);
}

        El contenido del archivo main.cpp es el siguiente: después de iniciar el programa qt, se llama al objeto QMoviePlayer definido anteriormente, se lee el archivo de video (argv [1]) y se actualiza la pantalla:

#include <QApplication>
#include <QMoviePlayer.h>

int main( int argc, char* argv[])
{
    QApplication app( argc, argv);
    QMoviePlayer mp;
    mp.open( argv[1]);
    mp.show();
    return app.exec();
}

3. Compilación y prueba.

        3.1 Compilación del programa

        Ingrese al directorio opencv_qt

        Ejecute vcbuild_2015.bat, la ejecución es aproximadamente la siguiente (este artículo se ejecuta directamente en la ventana de comando vscode):

        3.2 Programa en ejecución

         Ingrese opencv_qt\bin\Debug e inicie la ventana de comandos. Falta la biblioteca dinámica qt. Por lo tanto, copie la biblioteca dinámica qt en este directorio y ejecútela. Preste atención a la diferencia entre depuración y lanzamiento. Para mayor comodidad, este artículo también copia los archivos de video que deben ejecutarse en este directorio, como se muestra a continuación:

         Inicie la ventana de comandos y ejecute opencv_qt.exe

         El programa se inicia y el video se carga para su reproducción. Si el video no se puede reproducir normalmente, la información de salida del registro se puede usar para posicionamiento y solución de problemas.

Supongo que te gusta

Origin blog.csdn.net/py8105/article/details/132011276
Recomendado
Clasificación