- 20220720:对视频读取线程
frame
为空时进行处理。
- 本机环境
- QT 5.13.0
- Python 3.8.10
- VS2017 x64
- cuda 11.4
- opencv 4.5.2
- 所需环境
- QT >= Qt 5
- Python >= 3.7 (根据算法所用版本,例如
yolov5
需要Python>=3.7.0
,PyTorch>=1.7
)
git clone https://gitee.com/yunke120/qt-python-yolov5.git
.
├── bin/ /* release 目录 */
├── detectimage.cpp /* 检测图片线程源文件 */
├── detectimage.h /* 检测图片线程头文件 */
├── inc/ /* 外部头文件 */
├── libs/ /* 外部库文件 */
├── main.cpp /* 启动入口 */
├── mainwindow.cpp /* 主线程源文件 */
├── mainwindow.h /* 主线程(GUI)头文件 */
├── mainwindow.ui /* UI文件 */
├── paintlabel.cpp /* 重写QLabel源文件 */
├── paintlabel.h /* 重写QLabel头文件 */
├── README.md /* 说明 */
├── Demo.pro /* 工程文件 */
├── videoplayer.cpp /* 接收视频线程源文件 */
└── videoplayer.h /* 接收视频线程头文件 */
/bin文件结构:
├── opencv_videoio_ffmpeg452_64.dll /* 所需动态库 */
├── opencv_world452.dll
├── openh264-1.8.0-win64.dll
├── python38.dll
├── python3.dll
├── Demo.exe
└── yolov5/ /* 你的算法 */
在运行此程序之前,需要完成以下几步:
1、请确保您的Python
算法能够单独运行,这是为了确保能够成功调用Python
算法。
以YoloV5
为例,打开yolov5
文件夹,运行
python detect.py --weights yolov5s.pt --source data/images/bus.jpg
2、修改目录bin
、libs
、inc
下的python
相关文件。这些文件需要与你在步骤1中使用的Python
环境对应,查看当前Python
安装目录,执行命令where python
。
我所使用的Python 3.8.10
版本在第一个,打开这个路径G:\RJAZ\Miniconnda\data
,在里面找到python3.dll
和python38.dll
拷贝到bin
目录下; 打开.../data/libs
目录,拷贝python3.lib
和python38.lib
到libs
目录下;拷贝.../data/include
整个文件夹到inc
目录下,并改名为python
;修改其中的object.h
文件如下(slots关键字冲突了)
拷贝.../data/Lib/site-packages/numpy/core/include
下的numpy
文件夹到inc
目录下;
至此,python
所需文件都已经替换完毕。下面是代码的修改。
3、修改程序中相关代码
.pro
文件,宏USING_DETECT
开启检测,注销后不会启用检测
/* 可执行文件在这里,将算法和.dll放在这个bin文件夹下 */
DESTDIR = $$PWD/bin
/* LOGS目录为生成的中间文件,有时候代码出了莫名的错误可将此文件夹删除,再重新生成,说不定就解决了 */
OBJECTS_DIR = $$PWD/LOGS/temp/obj
MOC_DIR = $$PWD/LOGS/temp/moc
UI_DIR = $$PWD/LOGS/temp/ui
RCC_DIR = $$PWD/LOGS/temp/rcc
/* 这个宏定义USING_DETECT是开启算法检测的,如果注销后就只有视频播放 */
DEFINES += USING_DETECT
/* 头文件路径 */
INCLUDEPATH += $$PWD/inc
INCLUDEPATH += $$PWD/inc/python
/* 相关静态链接库 */
LIBS += -L$$PWD/libs \
-lopencv_world452 \
-lpython3 \
-lpython38
-
detectimage.cpp
文件pythonInit
函数:修改python
搜索路径和算法路径
run()
函数:修改要调用算法的模块名、类名、函数名等(需要修改以下yolov5
中的detect.py
函数,将其封装为一个类调用,请往下看)
mainwindow.cpp
文件
playerInit
函数:选择视频输入,支持usb
摄像头、本地视频和rtsp
等拉流方式
-
将
detect.py
封装为类进行调用 封装为类的好处是,只需在
python
算法初始化时加载一次模型,后续检测不需要重复加载,节省时间。Qt
需要给python
脚本传递图片,故检测函数detect
函数需要有一个入口参数frame
(一帧图像),经过模型检测后,将自己需要的结果return
即可。 在程序中
yolov5
的封装示例为temp.py
,其中类名为YoloV5
,变量初始化在__init__
中,加载模型函数为load_model
,图像检测函数为detect
,其输入为一个Mat
类型的图像,输出为检测之后的图像Mat
、图像的类列表和对应的置信度列表。 你需要将自己的算法封装为
temp.py
示例。 -
opencv
库需要自行编译,本文所用版本为opencv 4.5.2
,编译器为VS2017
,操作系统为Window10 64Bit
,你需要根据自己的环境编译opencv
版本库和opencv_contrib
版本库,编译时需勾选cuda
。最后替换文件夹中对应的文件即可。
PyImport_ImportModule
失败,很可能是python
文件中import
模块的问题,需要设置python
文件的搜索路径,一般来说通过PyRun_SimpleString("sys.path.append('/')");
就可以解决问题,如果依然加载失败,可以将模块的绝对路径或者相对路径也添加进去,如PyRun_SimpleString("sys.path.append('./python')");
,或者PyRun_SimpleString("sys.path.append('H:/substation-robot-dev/bin/meter')");
PyObject_CallObject
或者PyObject_CallMethod
这类函数返回空时,除了网上介绍的部分原因,另一方面可能是你调用的python
方法中存在打开open
或者加载load
文件等一系列与文件操作有关的代码,此时需要检查你的文件路径是否正确,按照我的程序所写,这个路径需要修改为相对于你的.exe
的路径,而不是相对于你的python module
路径。另外,返回空还算好的,程序直接崩溃才是最惨的,如果你用到的python
函数的返回值,再用PyArg_Parse
进行解析时,须保证传入的参数类型与返回值类型保持一致。具体对应关系可参考链接。- 如有其它问题,可在issue中提问。
点击跳转
Python C-API
文档