C/C++开发,opencv和qt结合播放视频
目录
首先声明,这是一个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内容如下:
-
-
<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!
-
********************************************************************************/
-
-
-
-
-
-
-
-
-
-
-
-
-
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
-
-
二、创建工程
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及代码头文件。
-
# 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”用来捕获视频内容:
-
-
-
-
-
-
-
-
-
-
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;
-
};
-
-
QMoviePlayer.cpp内容如下,open函数用于打开一个视频文件,并通过QTimer对象来定期读取帧图像数据,nextFrame用于读取图像数据并更新到窗口显示;_copyImage函数是opencv与QT结合的关键,它将opencv捕获的图像m_cv_img转换为qt的图像m_qt_img,这样才能将图片按qt方式刷新到窗口显示:
-
-
-
-
-
-
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])及刷新显示:
-
-
-
-
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
程序启动,加载视频进行播放,如果不能正常播放,可以通过日志输出信息进行定位排查。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhfgaiig
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
photoshop蒙版画笔没反应怎么办
PHP中文网 06-24