C/C++开发,opencv与qt结合播放视频

news2024/11/19 10:40:20

目录

一、qt_ui创建

        1.1 ui设置

         1.2 ui及代码输出保存

二、创建工程

        2.1 工程目录及编译设置

        2.2 源码设计

三、编译及测试

        3.1 程序编译

        3.2 程序运行


        首先声明,这是一个OpenCV 3学习文档的案例,但是说明有些过于省略,只有一些简短的代码描述,本人在学习验证过程中将其记录下来分享给大家。

一、qt_ui创建

        1.1 ui设置

        本文采用qt5.8_msvc2015_64版本,

        进入qt的bin目录,打开qt_ui设计工具designer.exe

         创建一个Widget窗体,即对象QWidget,命名为QMoviePlayer。

         随后创建一个QFrame对象,对象名为frame,该对象可以随意在窗体QMoviePlayer拉出一个合适的长宽比显示框,该显示框用来显示视频使用。

         完成设置后,保存该UI,例如QMoviePlayer.ui

         1.2 ui及代码输出保存

        本人的QMoviePlayer.ui文件的xml内容如下:

<?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>

        点击窗体菜单,进入查看代码,保存该代码文件为ui_QMoviePlayer.h,或新创建一个头文件将该内容直接复制到头文件中保存。

         本人的ui_QMoviePlayer.h的代码内容如下。

/********************************************************************************
** 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.1 工程目录及编译设置

        创建一个opencv_qt目录的工程文件,工程组织如下:

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和QMoviePlayer.ui就是前面采用designer.exe实现的ui及代码头文件。

        CMakeLists.txt文件内容如下,本文给出的有win/linux的痕迹,但是本文只实现了基于vc2015+qt_vc2015+opencv_vc的win编译方式,Linux下本文并没有进行测试,有兴趣的读者可以按该模块调整支持实现(关于opencv的Linux下库编译及调用案例看本专栏其他博文)。qt链接采用了动态库,opencv的基于vc2015编译出来的库本文时预先编译好的(C/C++开发,opencv在win下安装及应用_c++安装opencv库_py_free-物联智能的博客-CSDN博客)。

# 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是为了编译方便创建的一个脚本,读者也可以按该脚本命令手动编译。

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 源码设计

        下来看看源码如何实现视频读取与播放的。

        QMoviePlayer.h内容如下,该头文件定义了一个窗口类型,该窗口显示部分来自于前面的UI设计“Ui::QMoviePlayer ui”,定义了“cv::VideoCapture m_cap”用来捕获视频内容:

#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_

        QMoviePlayer.cpp内容如下,open函数用于打开一个视频文件,并通过QTimer对象来定期读取帧图像数据,nextFrame用于读取图像数据并更新到窗口显示;_copyImage函数是opencv与QT结合的关键,它将opencv捕获的图像m_cv_img转换为qt的图像m_qt_img,这样才能将图片按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);
}

        main.cpp文件内容如下,就是qt程序启动后,调用前面定义的QMoviePlayer对象,读取视频文件(argv[1])及刷新显示:

#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.1 程序编译

        进入opencv_qt目录

        运行vcbuild_2015.bat,执行大致如下(本文是直接在vscode命令窗口执行):

        3.2 程序运行

         进入opencv_qt\bin\Debug,启动命令窗口运行是缺失qt动态库的,因此将qt动态库拷贝到该目录下运行,注意debug和release的区别,为了方便,本文把需要运行的视频文件也拷贝到了该目录下,如下图:

         启动命令窗口,并运行opencv_qt.exe

         程序启动,加载视频进行播放,如果不能正常播放,可以通过日志输出信息进行定位排查。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/813299.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ubuntu20.04终端中文显示乱码

我在配置好ubuntu20.04虚拟机以后&#xff0c;用xshell连接到终端&#xff0c;发现中文来不能显示&#xff0c;尝试过设置xshell的显示格式&#xff0c;不能解决问题。 经过研究&#xff0c;发现要修改ubuntu20.04本身的字体格式&#xff0c;解决方式如下&#xff1a; 1.修改~…

JavaBean

一、JavaBean的概念 1、JavaBean就是MVC设计模式中的model层 2、种类&#xff1a;数据bean&#xff08;pojo&#xff09;&#xff0c;逻辑bean 数据bean分为&#xff1a; 表单bean 封装表单里的参数&#xff0c;属性名字、个数和类型要和表单的参数的名字、个数和类型一致…

我对排序算法理解

排序算法一直是一个很困惑我的问题&#xff0c;早在刚开始接触 数据结构的时候&#xff0c;这个地方就很让我不解。就是那种&#xff0c;总是感觉少了些什么的感觉。一开始&#xff0c;重新来过&#xff0c;认真来学习这一部分&#xff0c;也总是学着学着就把概念记住了。过了一…

【Rust学习 | 基础系列3 | Hello, Rust】编写并运行第一个Rust程序

文章目录 前言一&#xff0c;创建项目二&#xff0c;两种编译方式1. 使用rustc编译器编译2. 使用Cargo编译 总结 前言 在开始学习任何一门新的编程语言时&#xff0c;都会从编写一个简单的 “Hello, World!” 程序开始。在这一章节中&#xff0c;将会介绍如何在Rust中编写并运…

Elasticsearch搜索引擎系统入门

目录 【认识Elasticsearch】 Elasticsearch主要应用场景 Elasticsearch的版本与升级 【Elastic Stack全家桶】 Logstash Kibana Beats Elasticsearch在日志场景的应用 Elasticsearch与数据库的集成 【安装Elasticsearch】 安装插件 安装Kibana 安装Logstash 【认…

Day01-作业(HTMLCSS)

作业1&#xff1a;通过HTML的标签及CSS样式&#xff0c;完成如下企业简介html页面的制作。 【必做】 A. 最终效果如下&#xff1a; B. 文字素材如下&#xff1a; 企业简介传智教育(股票代码 003032)&#xff0c;隶属江苏传智播客教育科技股份有限公司&#xff0c;注册资本4亿元…

【NVIDIA CUDA】2023 CUDA夏令营编程模型(一)

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

【Git】Git GitHub

1. Git1.1 Git基本操作1.2 Git版本回退1.3 Git分支操作 2. Git 配合GitHub2.1 生成密钥2.2 GitHub添加公钥2.3 Git连接GitHub2.4 本地仓库关联远程仓库2.5 本地代码push远程仓库2.6 本地clone远程仓库2.7 本地fetch和pull 1. Git 1.1 Git基本操作 touch test.py 工作区创建文…

全网最细,Postman接口测试实战详细总结,一篇进阶...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Postman是一款功能…

【力扣每日一题】2023.7.30 环形链表2

题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 这道题属于是那种知道解法就很简单&#xff0c;不知道解法就很难独立想出来的那种&#xff0c;我们只需要稍微记住这类题的固定解法就可以。 所以接下来我先说解法&#xff0c;再解释为什么解法可以解出来。 那么我们都…

nginx使用-(想学nginx,这篇就够了)

nginx使用-&#xff08;想学nginx&#xff0c;这篇就够了&#xff09; upstream wgz{server 127.0.0.1:8081 ;server 127.0.0.1:8082 ;fair;}反向代理 动静分离 负载均衡 高可用集群配置 反向代理 upstream要转发的地址的配置proxy_pass请求转发的地址 location /user{proxy_…

程序设计 算法基础

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

【并发专题】操作系统模型及三级缓存架构

目录 课程内容一、冯诺依曼计算机模型详解1.计算机五大核心组成部分2.CPU内部结构3.CPU缓存结构4.CPU读取存储器数据过程5.CPU为何要有高速缓存 学习总结 课程内容 一、冯诺依曼计算机模型详解 现代计算机模型是基于-冯诺依曼计算机模型 计算机在运行时&#xff0c;先从内存中…

python学习之【浅拷贝】

前言 上一篇文章&#xff0c;python学习之【继承、封装、多态】主要学习了面向对象的三大特征。这篇文章记录下对python的浅拷贝的学习&#xff0c;下一篇文章接着学习深拷贝。 简单了解 浅拷贝&#xff1a;python拷贝一般都是浅拷贝&#xff0c;拷贝时&#xff0c;对象包含的…

【C语言】函数重难点之函数递归

大家好&#xff0c;我是深鱼~ 目录 一、函数递归知识讲解 1.什么是递归&#xff1f; 2.递归的两个必要条件 2.1练习1&#xff1a; 2.2练习2&#xff1a; 二、递归与迭代 2.1练习3 2.2练习4 一、函数递归知识讲解 1.什么是递归&#xff1f; 程序调用自身的编程技巧称为…

UNITY随记(八) SHADER实现立方体CUBE显示边框,描边

Shader "Vitens/CubeOutline"{Properties{_Color("Color", color) = (1,1,1,1)_Width("Width", range(0,0.5)) = 0.1}SubShader{Tags {"Queue"=

windows下载安装FFmpeg

FFmpeg是一款强大的音视频处理软件&#xff0c;下面介绍如何在windows下下载安装FFmpeg 下载 进入官网: https://ffmpeg.org/download.html, 选择Windows, 然后选择"Windows builds from gyan.dev" 在弹出的界面中找到release builds, 然后选择一个版本&#xff0…

Java中的生产者/消费者模型

一、什么是生产者/消费者模型 生产者-消费者模型&#xff08;Producer-Consumer problem&#xff09;是一个非常经典的多线程并发协作的模型。 比如某个模块负责生产数据&#xff0c;而另一个模块负责处理数据。产生数据的模块就形象地被称为生产者&#xff1b;而处理数据的模…

基地培训一周总结-用两台虚拟机模拟公司和员工

前言&#xff1a; 本来是打算每天跟更新所学内容&#xff0c;但奈何自己接触新知识速度较慢&#xff0c;每天都在完不成任务的边缘疯狂试探&#xff0c;短时间大量知识的涌入&#xff0c;感觉脑袋瓜在有点 跟不上。这周结束的时候&#xff0c;老师布置了个小项目&#xff0c;融…

Linux操作系统下安装python环境

参考&#xff1a;Linux操作系统下安装python环境_linux如何下载python_秃头小猿-F的博客-CSDN博客 注意 切换用户 二、切换root用户 1.给root用户设置密码&#xff1a;命令&#xff1a;sudo passwd root输入密码&#xff0c;并确认密码。2.重新输入命令&#xff1a;su root …