赞
踩
本文是基于qt和opencv的dnn深度学习推理模块,在树莓派上部署YOLO系列推理,适用于yolov5-6.1以及yolov5-Lite,相比直接用python的onnxruntime,用基于opencv的dnn模块,利用训练生成的onnx模型,即可快速部署,不需要在树莓派上额外安装深度学习的一系列环境,因为我们知道部署环境是比较玄学的,也是比较麻烦的。
刚开始使用的是YOLOv5-6.1版本,部署在电脑虚拟机上能达到7fps,但是如果在树莓派上运行,速度极慢,基本上fps在0.3左右,即推理一次所需的时间在3s以上,实际上根本达不到实时的要求。因此,作者换了更轻量化的网络yoloV5-Lite,部署完成后fps大概在1.54左。之前看到过有作者直接用onnxruntime推理fps能达到5左右,可能是因为qt占树莓派运行内存较大,故很慢。
因此本文首先是使用海康工业相机采集到需要的数据集,然后在PC端利用YOLOV5-Lite网络进行训练,训练完成之后,将生成的.pt(pytorch格式)权重文件转换为.onnx格式,方便后续利用opencv的dnn模块直接推理。在得到了onnx权重文件后,在树莓派上部署推理所需的环境,即安装qt和opencv。配置好环境后,在qt开发一个简单的界面,根据自己的需求,将所有模块融合进去,最后就可以推理成功啦。话不多说,作者的简单界面是这样的。
下面就开始逐步跟大家讲一下实现过程。
由于作者做的是工业相关的一个小项目,基于甲方提供的设备,数据集采集是使用海康威视的工业相机,后续实时推理也是连接了海康工业相机,具体如何在Linux系统下,使用qt成功控制海康工业相机,链接里面有详细说明。有些同学可能使用的是公开的数据集,那这节可以略过。至于给数据集打标签以及配置深度学习环境等一系列问题,作者参考的是良心up炮哥,链接放下面目标检测---教你利用yolov5训练自己的目标检测模型,此外他还有很多博客,可以从0环境到实现搭建深度学习YOLOv5所需的所有环境,因为YOLOV5-Lite和YOLOV5所需的环境是一样的,所以可以直接拿来用。
训练模型过程中,都是常用的参数更改,根据自己的数据集路径,更改yaml文件等操作,这里不再赘述,上节链接中作者的博客中都有,触类旁通,yolov5-Lite也是一样的。训练完成后可以发现在train文件夹下exp...某个文件夹中生成了best.pt和last.pt,使用best.pt就可以转换为onnx格式啦。
这一步是至关重要的,直接关乎到是否能推理成功。至于如何转onnx,yolov5作者都有写,运行export.py就可以转换成功。
作者的代码适用于推理YOLOv5-6.1或者onnx输出后整合为单一通道的格式,如下图,其中output就是将三个尺度,也就是80,40,20整合为一个输出,方便后续推理的时候读取。
当然,也可以使用下图中的格式,只是需要在推理的时候改一下代码,后续会讲到
对于树莓派安装qt,可以参考以下博客,还是比较简单的,具体可以搜一下教程,基本都可以成功,但是要注意,qt在5.14版本以后变成了online安装,也就是线上安装,因此树莓派必须成功联网,不然安装不上,作者安装的qt版本是5.14.2。
安装opencv可以说是很玄学的,你是天选之子,那一次就可以成功,但作者并非是,在树莓派配置opencv环境过程中,足足花费了一下午时间,一直在处理报错的路上,作者也整理了一下如何在Linux下配置opencv,下面就细细讲解一下。
https://opencv.org/releases.html,找到对应的版本安装,但注意,opencv4.5以上版本才支持dnn推理,也就是深度学习模型的读取,不能安装低于4.5的版本。
在下载好了压缩包后,右键提取到当前目录下,然后进入opencv4.7.0
目录中,并在opencv-4.7.0下创建键build和install两个文件夹,后续编译会用到。
下面就是安装Cmake和Cmake-gui以及所依赖的库(若出错可以思考一下是否执行了sudo apt update与sudo apt upgrade),执行如下代码
- sudo apt-get install cmake-qt-gui
- sudo apt-get install build-essential
- sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
进入build文件夹下编译cmake ,执行命令
cmake-gui
打开了cmake-gui图形化界面,需要更改的地方如下图所示
首先,1是我们解压好的opencv安装包的路径,2处选择build文件夹的路径 ,记得一定要勾选3处Advanced。然后就可以点击configure开始配置了。在configure done之后,我们不需要改路径,直接保持默认路径/usr/local,不然会出现各种报错。如下图
然后继续configure和generate之后,没有红色提示说明配置成功。如果出现了红色问题,那就搜一搜报错,应该都能搜到解决方法。
下面就是进入到build文件夹目录下,开始执行命令
- sudo make -j4
- sudo make install
开始了漫长的编译之路,希望每位读者都能一次到100%,如果没到,那就开始和作者一样的痛苦改错日记吧。
在完成了编译之后,需要配置opencv的环境变量,进入目录
- cd /etc/ld.so.conf.d/
- sudo vim opencv.conf
创建文件后插入
/usr/local
保存并退出,执行:
sudo ldconfig
下面就是配置bash,
sudo vim /etc/bash.bashrc
在末尾添加:
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/pkgconfig
export PKG_CONFIG_PATH
保存退出:执行
source /etc/bash.bashrc
最后就是安装mlocate
- sudo apt-get update
- sudo apt-get install mlocate
执行更新资料库:
sudo updatedb
最后就可以找一个opencv的qt程序测试一下,能不能打开一张图片之类的。opencv的部署就至此结束啦
这部分没有什么需要细讲的,直接上代码:
- #include "widget.h"
- #include "mainwidget.h"
- #include "yolov5.h"
- #include <QApplication>
- #include <math.h>
- using namespace std;
- using namespace cv;
- using namespace dnn;
-
-
-
- int main(int argc, char *argv[])
- {
- QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
- QApplication a(argc, argv);
- MainWidget mw;
- mw.show();
- return a.exec();
- }
此处是将mainWeight为主窗体运行,其他没有任何额外的功能
头文件有如上五个,其中mainwidget是主窗体的头文件,MVCamera.h是海康相机相关的,mythread.h是创建一个独立的线程,以此来控制相机传过来的图像间隔,如果单纯检测视频的话,可以不用这个。widget.h也是海康工业相机的相关头文件,yolov5.h是有关推理的,着重讲一下这个,其他的我相信大家都能看懂,我直接附代码
- #ifndef MAINWIDGET_H
- #define MAINWIDGET_H
- #define MAX_MAINDEVICE_NUM 255
- #include "ui_widget.h"
- #include "ui_mainwidget.h"
- #include "widget.h"
- #include <QFileDialog>
- #include <QFile>
- #include <opencv2/opencv.hpp>
- #include <opencv2/dnn.hpp>
- #include <QMainWindow>
- #include <QTimer>
- #include <QImage>
- #include <QPixmap>
- #include <QDateTime>
- #include <QMutex>
- #include <QMutexLocker>
- #include <QMimeDatabase>
- #include <iostream>
- #include "MvCamera.h"
- #include <chrono>
- #include<math.h>
- #include <opencv2/highgui/highgui.hpp>
- #include "mythread.h"
- #include "yolov5.h"
- #include <QLineEdit>
- #include <QTextCursor>
-
- using namespace cv;
- using namespace std;
- using namespace dnn;
-
- QPixmap MatImage(cv::Mat src);
-
- QT_BEGIN_NAMESPACE
- namespace Ui {
- class MainWidget;
- }
-
- class Widget; //前向声明,在qt中要用另一个类时
- class CMvCamera;
- class YoloV5;
- class MainWidget : public QWidget
- {
- Q_OBJECT
-
- public:
- explicit MainWidget(QWidget *parent = nullptr);
- //存储相机配置界面的指针
- Widget *wid=NULL;
-
- CMvCamera *m_pcMyMainCamera[MAX_MAINDEVICE_NUM]; // 相机指针对象
-
- cv::Mat *myImage_Main = new cv::Mat(); //保存相机图像的图像指针对象
-
- MyThread *myThread_Camera_Mainshow = NULL; //相机画面实时显示线程对象
-
- std::vector<std::string> className1 = { /*"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
- "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
- "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
- "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
- "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
- "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
- "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
- "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",
- "hair drier", "toothbrush" */"OK","NG"};
-
- Ui::MainWidget *ui;
- ~MainWidget();
- public:
- // 状态
- bool m_bOpenDevice; // 是否打开设备
- bool m_bStartGrabbing; // 是否开始抓图
- int m_nTriggerMode; // 触发模式
- int m_bContinueStarted;
- int num;
- // 开启过连续采集图像
- MV_SAVE_IAMGE_TYPE m_nSaveImageType; // 保存图像格式
-
- YoloV5 yolov5;
-
- Net net;
- private slots:
- void on_pbn_start_grab_clicked();
-
- void closeW(); //关闭子窗体的槽函数
-
- void readFrame();
-
- void on_openfile_clicked();
-
- void on_pbn_load_model_clicked();
-
- void on_startdetect_clicked();
-
- void on_stopdetect_clicked();
-
- void on_cbx_modelName_activated(const QString &arg1);
-
- void display_myImage_Main(const Mat *imagePrt);
-
- void getPtr();
-
- void yoloDetect( Mat *imagePrt);
- //void showCamera();
- void on_checkBox_stateChanged(int arg1);
-
- private:
-
- QTimer *timer;
- cv::VideoCapture *capture;
-
-
- std::vector<cv::Rect> bboxes;
- int IsDetect_ok =0;
-
- };
-
- #endif // MAINWIDGET_H
- #ifndef MVCAMERA_H
- #define MVCAMERA_H
-
- #include "MvCameraControl.h"
- #include <string.h>
- #include <QDebug>
- #include <stdio.h>
-
- #ifndef MV_NULL
- #define MV_NULL 0
- #endif
-
- #include "opencv2/opencv.hpp"
- #include "opencv2/imgproc/types_c.h"
-
- class CMvCamera
- {
- public:
- CMvCamera();
- ~CMvCamera();
-
- // ch:获取SDK版本号 | en:Get SDK Version
- static int GetSDKVersion();
-
- // ch:枚举设备 | en:Enumerate Device
- static int EnumDevices(unsigned int nTLayerType,
- MV_CC_DEVICE_INFO_LIST *pstDevList);
-
- // ch:判断设备是否可达 | en:Is the device accessible
- static bool IsDeviceAccessible(MV_CC_DEVICE_INFO *pstDevInfo,
- unsigned int nAccessMode);
-
- // ch:打开设备 | en:Open Device
- int Open(MV_CC_DEVICE_INFO *pstDeviceInfo);
-
- // ch:关闭设备 | en:Close Device
- int Close();
-
- // ch:判断相机是否处于连接状态 | en:Is The Device Connected
- bool IsDeviceConnected();
-
- // ch:注册图像数据回调 | en:Register Image Data CallBack
- int RegisterImageCallBack(
- void(__stdcall *cbOutput)(unsigned char *pData,
- MV_FRAME_OUT_INFO_EX *pFrameInfo,
- void *pUser),
- void *pUser);
-
- // ch:开启抓图 | en:Start Grabbing
- int StartGrabbing();
-
- // ch:停止抓图 | en:Stop Grabbing
- int StopGrabbing();
-
- // ch:主动获取一帧图像数据 | en:Get one frame initiatively
- int GetImageBuffer(MV_FRAME_OUT *pFrame, int nMsec);
-
- // ch:释放图像缓存 | en:Free image buffer
- int FreeImageBuffer(MV_FRAME_OUT *pFrame);
-
- // ch:主动获取一帧图像数据 | en:Get one frame initiatively
- int GetOneFrameTimeout(unsigned char *pData, unsigned int *pnDataLen,
- unsigned int nDataSize,
- MV_FRAME_OUT_INFO_EX *pFrameInfo, int nMsec);
-
- // ch:显示一帧图像 | en:Display one frame image
- int DisplayOneFrame(MV_DISPLAY_FRAME_INFO *pDisplayInfo);
-
- // ch:设置SDK内部图像缓存节点个数 | en:Set the number of the internal image
- // cache nodes in SDK
- int SetImageNodeNum(unsigned int nNum);
-
- // ch:获取设备信息 | en:Get device information
- int GetDeviceInfo(MV_CC_DEVICE_INFO *pstDevInfo);
-
- // ch:获取GEV相机的统计信息 | en:Get detect info of GEV camera
- int GetGevAllMatchInfo(MV_MATCH_INFO_NET_DETECT *pMatchInfoNetDetect);
-
- // ch:获取U3V相机的统计信息 | en:Get detect info of U3V camera
- int GetU3VAllMatchInfo(MV_MATCH_INFO_USB_DETECT *pMatchInfoUSBDetect);
-
- // ch:获取和设置Int型参数,如 Width和Height,详细内容参考SDK安装目录下的
- // MvCameraNode.xlsx 文件 en:Get Int type parameters, such as Width and
- // Height, for details please refer to MvCameraNode.xlsx file under SDK
- // installation directory
- // int GetIntValue(IN const char* strKey, OUT MVCC_INTVALUE_EX* pIntValue);
- int GetIntValue(IN const char *strKey, OUT unsigned int *pnValue);
- int SetIntValue(IN const char *strKey, IN int64_t nValue);
-
- // ch:获取和设置Enum型参数,如 PixelFormat,详细内容参考SDK安装目录下的
- // MvCameraNode.xlsx 文件 en:Get Enum type parameters, such as PixelFormat,
- // for details please refer to MvCameraNode.xlsx file under SDK installation
- // directory
- int GetEnumValue(IN const char *strKey, OUT MVCC_ENUMVALUE *pEnumValue);
- int SetEnumValue(IN const char *strKey, IN unsigned int nValue);
- int SetEnumValueByString(IN const char *strKey, IN const char *sValue);
-
- // ch:获取和设置Float型参数,如
- // ExposureTime和Gain,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
- // en:Get Float type parameters, such as ExposureTime and Gain, for details
- // please refer to MvCameraNode.xlsx file under SDK installation directory
- int GetFloatValue(IN const char *strKey, OUT MVCC_FLOATVALUE *pFloatValue);
- int SetFloatValue(IN const char *strKey, IN float fValue);
-
- // ch:获取和设置Bool型参数,如 ReverseX,详细内容参考SDK安装目录下的
- // MvCameraNode.xlsx 文件 en:Get Bool type parameters, such as ReverseX, for
- // details please refer to MvCameraNode.xlsx file under SDK installation
- // directory
- int GetBoolValue(IN const char *strKey, OUT bool *pbValue);
- int SetBoolValue(IN const char *strKey, IN bool bValue);
-
- // ch:获取和设置String型参数,如 DeviceUserID,详细内容参考SDK安装目录下的
- // MvCameraNode.xlsx 文件UserSetSave en:Get String type parameters, such as
- // DeviceUserID, for details please refer to MvCameraNode.xlsx file under
- // SDK installation directory
- int GetStringValue(IN const char *strKey, MVCC_STRINGVALUE *pStringValue);
- int SetStringValue(IN const char *strKey, IN const char *strValue);
-
- // ch:执行一次Command型命令,如 UserSetSave,详细内容参考SDK安装目录下的
- // MvCameraNode.xlsx 文件 en:Execute Command once, such as UserSetSave, for
- // details please refer to MvCameraNode.xlsx file under SDK installation
- // directory
- int CommandExecute(IN const char *strKey);
-
- // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal
- // package size(It only works for the GigE camera)
- int GetOptimalPacketSize(unsigned int *pOptimalPacketSize);
-
- // ch:注册消息异常回调 | en:Register Message Exception CallBack
- int RegisterExceptionCallBack(
- void(__stdcall *cbException)(unsigned int nMsgType, void *pUser),
- void *pUser);
-
- // ch:注册单个事件回调 | en:Register Event CallBack
- int RegisterEventCallBack(
- const char *pEventName,
- void(__stdcall *cbEvent)(MV_EVENT_OUT_INFO *pEventInfo, void *pUser),
- void *pUser);
-
- // ch:强制IP | en:Force IP
- int ForceIp(unsigned int nIP, unsigned int nSubNetMask,
- unsigned int nDefaultGateWay);
-
- // ch:配置IP方式 | en:IP configuration method
- int SetIpConfig(unsigned int nType);
-
- // ch:设置网络传输模式 | en:Set Net Transfer Mode
- int SetNetTransMode(unsigned int nType);
-
- // ch:像素格式转换 | en:Pixel format conversion
- int ConvertPixelType(MV_CC_PIXEL_CONVERT_PARAM *pstCvtParam);
-
- // ch:保存图片 | en:save image
- int SaveImage(MV_SAVE_IMAGE_PARAM_EX *pstParam);
-
- // ch:保存图片为文件 | en:Save the image as a file
- //int SaveImageToFile(MV_SAVE_IMG_TO_FILE_PARAM *pstParam);
-
- //设置是否为触发模式
- int setTriggerMode(unsigned int TriggerModeNum);
-
- //设置触发源
- int setTriggerSource(unsigned int TriggerSourceNum);
-
- //软触发
- int softTrigger();
-
- //读取buffer
- int ReadBuffer(cv::Mat &image);
-
- //读取buffer
- int ReadBuffer2(cv::Mat &image,bool saveFlag,QByteArray imageName);
-
- //设置曝光时间
- int setExposureTime(float ExposureTimeNum);
-
- public:
- void *m_hDevHandle;
- unsigned int m_nTLayerType;
-
- public:
- unsigned char *m_pBufForSaveImage; // 用于保存图像的缓存
- unsigned int m_nBufSizeForSaveImage;
-
- unsigned char *m_pBufForDriver; // 用于从驱动获取图像的缓存
- unsigned int m_nBufSizeForDriver;
- };
-
- #endif // MVCAMERA_H
- #ifndef MYTHREAD_H
- #define MYTHREAD_H
-
- #include "QThread"
- #include "MvCamera.h"
- #include "opencv2/opencv.hpp"
- #include "opencv2/core/core.hpp"
- #include "opencv2/calib3d/calib3d.hpp"
- #include "opencv2/highgui/highgui.hpp"
-
- #include <vector>
- #include <string>
- #include <algorithm>
- #include <iostream>
- #include <iterator>
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <QTimer>
- using namespace std;
- using namespace cv;
-
- class MyThread :public QThread
- {
- Q_OBJECT
-
- public:
- MyThread();
- ~MyThread();
-
- void run();
- void getCameraPtr(CMvCamera* camera);
- void getImagePtr(Mat* image);
- void getCameraIndex(int index);
-
- signals:
- void mess();
- void Display(const Mat* image);
-
- //发送获取图像处理的信号
- void GetPtr(Mat* image2);
-
- private:
- CMvCamera* cameraPtr = NULL;
- cv::Mat* imagePtr = NULL;
- //cv::Mat* imagePtr2 = NULL;
- int cameraIndex ;
- int TriggerMode;
-
- QTimer *time;
-
- };
-
- #endif // MYTHREAD_H
- #ifndef WIDGET_H
- #define WIDGET_H
-
- #include <QWidget>
-
- #include <QMessageBox>
- #include <QCloseEvent>
- #include <QSettings>
- #include <QDate>
- #include <QDir>
-
- #include "MvCamera.h"
- #include "mythread.h"
- #include "mainwidget.h"
-
- #define MAX_DEVICE_NUM 2
- #define TRIGGER_SOURCE 7
- #define EXPOSURE_TIME 40000
- #define FRAME 30
- #define TRIGGER_ON 1
- #define TRIGGER_OFF 0
- #define START_GRABBING_ON 1
- #define START_GRABBING_OFF 0
- #define IMAGE_NAME_LEN 64
-
-
- QT_BEGIN_NAMESPACE
- namespace Ui {
- class Widget;
- }
- QT_END_NAMESPACE
-
- class MainWidget;
- class Widget : public QWidget
- {
- Q_OBJECT
-
- public:
- Widget(QWidget *parent = nullptr);
- ~Widget();
- signals:
- void closedWid();
- void back();
-
- public:
- CMvCamera *m_pcMyCamera[MAX_DEVICE_NUM]; // 相机指针对象
- MV_CC_DEVICE_INFO_LIST m_stDevList; // 存储设备列表
- cv::Mat *myImage_L = new cv::Mat(); //保存左相机图像的图像指针对象
- cv::Mat *myImage_R = new cv::Mat(); //保存右相机有图像的图像指针对象
- int devices_num; // 设备数量
-
- MainWidget *mainWid = NULL; //创建一个存储主界面窗体的指针
- public:
- MyThread *myThread_Camera_show = NULL; //相机实时显示线程对象
-
- private slots:
- void on_pbn_enum_camera_clicked();
- void on_pbn_open_camera_clicked();
- void on_rdo_continue_mode_clicked();
- void on_rdo_softigger_mode_clicked();
- void on_pbn_start_grabbing_clicked();
- void on_pbn_stop_grabbing_clicked();
- void on_pbn_software_once_clicked();
- void display_myImage_L(const Mat *imagePrt);
- void display_myImage_Main(const Mat *imagePrt);
- void on_pbn_close_camera_clicked();
- void on_pbn_save_BMP_clicked();
- void on_pbn_save_JPG_clicked();
- void on_le_set_exposure_textChanged(const QString &arg1);
- void on_le_set_gain_textChanged(const QString &arg1);
-
-
-
- void on_pbn_return_main_clicked();
-
- public:
- // 状态
- bool m_bOpenDevice; // 是否打开设备
- bool m_bStartGrabbing; // 是否开始抓图
- int m_nTriggerMode; // 触发模式
- int m_bContinueStarted; // 开启过连续采集图像
- MV_SAVE_IAMGE_TYPE m_nSaveImageType; // 保存图像格式
-
- private:
- QString PrintDeviceInfo(MV_CC_DEVICE_INFO *pstMVDevInfo, int num_index);
- QString m_SaveImagePath;
- void OpenDevices();
- void CloseDevices();
- void SaveImage();
- void saveImage(QString format,int index);
-
- private:
-
- Ui::Widget *ui;
-
- protected:
- void closeEvent(QCloseEvent *event) override; //重写关闭事件处理函数
- };
- #endif // WIDGET_H
-
- #pragma once
- #include<iostream>
- #include<opencv2/opencv.hpp>
- using namespace std;
- #include <QString>
- #define YOLO_P6 false //是否使用P6模型
- #include<math.h>
-
- struct Output {
- int id; //结果类别id
- float confidence; //结果置信度
- cv::Rect box; //矩形框
- };
-
- class YoloV5 {
- public:
- YoloV5() {
- }
- ~YoloV5() {}
- bool readModel(cv::dnn::Net& net, std::string& netPath, bool isCuda);
- bool Detect(cv::Mat& SrcImg, cv::dnn::Net& net, std::vector<Output>& output);
- void drawPred(cv::Mat& img, std::vector<Output> result, std::vector<cv::Scalar> color);
- void getTime(QString msg);
- private:
- float Sigmoid(float x) {
- return static_cast<float>(1.f / (1.f + exp(-x)));
- }
-
- const float netAnchors[3][6] = { { 10.0, 13.0, 16.0, 30.0, 33.0, 23.0 },{ 30.0, 61.0, 62.0, 45.0, 59.0, 119.0 },{ 116.0, 90.0, 156.0, 198.0, 373.0, 326.0 } };
- //stride
- const float netStride[3] = { 8.0, 16.0, 32.0 };
- const int netWidth = 320; //网络模型输入大小
- const int netHeight = 320;
- float nmsThreshold = 0.45;
- float boxThreshold = 0.35;
- float classThreshold = 0.35;
- public:
- std::vector<std::string> className = { /*"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
- "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
- "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
- "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
- "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
- "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
- "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
- "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",
- "hair drier", "toothbrush" */"OK","NG"};
- };
这里需要讲一下,对于vector数组className,需要设置自己的类别数,这里需要改一下,因为作者的类别数只有“ok”和“NG”,所有我将原有的数据集coco的80个类别给注释掉了,自己根据需求更改相关参数,都在头文件里。
- #include "mainwidget.h"
- #include "ui_mainwidget.h"
- #include "widget.h"
- #include <QPushButton>
-
- MainWidget::MainWidget(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::MainWidget)
- {
- ui->setupUi(this);
- setWindowTitle(QStringLiteral("4079Lab"));
- ui->lbl_res_pic->setScaledContents(true);
- ui->txt_message->setLineWrapMode(QTextEdit::WidgetWidth);
- timer =new QTimer(this);
- timer->setInterval(30); //设置定时器触发的间隔
-
- num=1;
- //将定时器与读取数据流的函数连接起来,每当定时器触发,执行readFrame
- connect(timer,&QTimer::timeout,this,&MainWidget::readFrame);
-
- //将定时器与读取相机帧率以及检测的函数连接起来,每当定时器触发,执行yoloDetect
-
- //ui->startdetect->setEnabled(false);
-
- this->wid=new Widget();
- //点击相机配置按钮,显示相机配置界面,隐藏主界面
- connect(ui->pbn_start_grab,&QPushButton::clicked,wid,[=]()
- {
- this->hide();
- wid->show();
- });
-
- //关闭相机配置界面后,显示主界面
- connect(this->wid, &Widget::closedWid, this,[=]()
- {
- this->show();
- });
-
- //主界面接受信号后,会显示主界面,隐藏相机界面
- connect(this->wid,&Widget::back,this,[=]()
- {
- this->wid->hide();
- this->show();
-
- });
-
- this->myThread_Camera_Mainshow=new MyThread;
- connect(wid->myThread_Camera_show, SIGNAL(GetPtr(Mat *)), this,
- SLOT(yoloDetect(Mat *)));
-
- //设置打开图片和摄像头button为disable,只有当加载模型后才会Enable
- ui->openfile->setEnabled(false);
- ui->pbn_start_grab->setEnabled(false);
- }
- MainWidget::~MainWidget()
- {
- capture->release();
- delete capture;
- delete ui;
- delete wid;
-
-
- }
-
-
- //读取流函数
- void MainWidget::readFrame()
- {
- cv::Mat frame;
- capture->read(frame);
- if (frame.empty())
- return;
-
- auto start = std::chrono::steady_clock::now();
- //yolov5->detect(frame);
- auto end = std::chrono::steady_clock::now();
- std::chrono::duration<double, std::milli> elapsed = end - start;
- ui->txt_message->append(QString("cost_time: %1 ms").arg(elapsed.count()));
- cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);
- QImage rawImage = QImage((uchar*)(frame.data),frame.cols,frame.rows,frame.step,QImage::Format_RGB888);
- ui->lbl_res_pic->setPixmap(QPixmap::fromImage(rawImage));
- }
-
-
- //根据定时器触发实时检测
- void MainWidget::yoloDetect(Mat *myImage_Main)
- {
-
- //读取相机流
- //m_pcMyMainCamera[0]->ReadBuffer(*myImage_Main);
- if(myImage_Main!=NULL)
- {
- cv::Mat temp;
- if(myImage_Main->channels()==4)
- cv::cvtColor(*myImage_Main,temp,cv::COLOR_BGRA2RGB);
- else if (myImage_Main->channels()==3)
- cv::cvtColor(*myImage_Main,temp,cv::COLOR_BGR2RGB);
- else
- cv::cvtColor(*myImage_Main,temp,cv::COLOR_GRAY2RGB);
- vector<Scalar> color;
- srand(time(0));
- for (int i = 0; i < 80; i++) {
- int b = rand() % 256;
- int g = rand() % 256;
- int r = rand() % 256;
- color.push_back(Scalar(b, g, r));
- }
- vector<Output> result;
-
-
- auto start = std::chrono::steady_clock::now();
- yolov5.Detect(temp,net,result);
- auto end = std::chrono::steady_clock::now();
- std::chrono::duration<double, std::milli> elapsed = end - start;
-
- ui->time_tet->setOverwriteMode(true);
- ui->time_tet->setText(QString("%1 ms").arg(elapsed.count()));
-
- ui->txt_message->append(QString("%1 result:%2 const_time: %3 ms").arg(num).arg((className1[result[0].id].data())).arg(elapsed.count()));
- yolov5.drawPred(temp, result, color);
- QImage img = QImage((uchar*)(temp.data),temp.cols,temp.rows,temp.step,QImage::Format_RGB888);
- ui->lbl_res_pic->setPixmap(QPixmap::fromImage(img));
- ui->lbl_res_pic->resize(ui->lbl_res_pic->pixmap()->size());
- if(ui->checkBox->isChecked())
- {
- QString savePath="/home/joe/program/VersionDetect/LiteTest/res_img/num.png";
- img.save(savePath);
- }
- result.pop_back();
- num++;
- }
-
-
- }
-
- //加载相机界面
- void MainWidget::on_pbn_start_grab_clicked()
- {
- // QString onnxFile = "/home/joe/program/VersionDetect/test2/yolov5s.onnx";
-
- // if (!yolov5->loadModel(onnxFile.toLatin1().data())){
- // ui->txt_message->append(QStringLiteral("加载模型失败!"));
- // return;
- // }
- // ui->txt_message->append(QString::fromUtf8("Open onnxFile: %1 succesfully!").arg(onnxFile));
- }
-
- //关闭子窗体 显示父窗体
- void MainWidget::closeW()
- {
- this->show();
- }
-
-
-
-
- //打开文件按钮的槽函数
- void MainWidget::on_openfile_clicked()
- {
-
- //过滤除了"*.mp4 *.avi;;*.png *.jpg *.jpeg *.bmp"以外的文件
- QString filename = QFileDialog::getOpenFileName(this,QStringLiteral("打开文件"),"/home/joe/onnx",".*.png *.jpg *.jpeg *.bmp;;*.mp4 *.avi");
- if(!QFile::exists(filename)){
- return;
- }
-
- QMimeDatabase db;
- QMimeType mime = db.mimeTypeForFile(filename);
- if (mime.name().startsWith("image/")) {
- cv::Mat src = cv::imread(filename.toLatin1().data());
- if(src.empty()){
- return;
- }
- cv::Mat temp;
- if(src.channels()==4)
- cv::cvtColor(src,temp,cv::COLOR_BGRA2RGB);
- else if (src.channels()==3)
- cv::cvtColor(src,temp,cv::COLOR_BGR2RGB);
- else
- cv::cvtColor(src,temp,cv::COLOR_GRAY2RGB);
- cv::Mat Rgb;
- QImage Img;
- if (src.channels() == 3)//RGB Img
- {
- cv::cvtColor(temp, Rgb, CV_BGR2RGB);//颜色空间转换
- Img = QImage((const uchar*)(Rgb.data), Rgb.cols, Rgb.rows, Rgb.cols * Rgb.channels(), QImage::Format_RGB888);
- }
- else//Gray Img
- {
- Img = QImage((const uchar*)(temp.data), temp.cols, temp.rows, temp.cols*temp.channels(), QImage::Format_Indexed8);
- }
- ui->lbl_res_pic->setPixmap(QPixmap::fromImage(Img));
- ui->lbl_res_pic->resize(ui->lbl_res_pic->pixmap()->size());
-
- vector<Scalar> color;
- srand(time(0));
- for (int i = 0; i < 80; i++) {
- int b = rand() % 256;
- int g = rand() % 256;
- int r = rand() % 256;
- color.push_back(Scalar(b, g, r));
- }
- vector<Output> result;
-
- auto start = std::chrono::steady_clock::now();
- yolov5.Detect(temp,net,result);
- auto end = std::chrono::steady_clock::now();
- std::chrono::duration<double, std::milli> elapsed = end - start;
- ui->txt_message->append(QString("%1 result:%2 const_time: %3 ms").arg(num).arg((className1[result[0].id].data())).arg(elapsed.count()));
- //ui->txt_message->append(QString("cost_time: %1 ms").arg(elapsed.count()));
-
- ui->time_tet->setOverwriteMode(true);
- ui->time_tet->setText(QString("%1 ms").arg(elapsed.count()));
-
- yolov5.drawPred(temp, result, color);
- QImage img = QImage((uchar*)(temp.data),temp.cols,temp.rows,temp.step,QImage::Format_RGB888);
- ui->lbl_res_pic->setPixmap(QPixmap::fromImage(img));
- ui->lbl_res_pic->resize(ui->lbl_res_pic->pixmap()->size());
- if(ui->checkBox->isChecked())
- {
- QString savePath="/home/joe/program/VersionDetect/LiteTest/res_img/num.png";
- img.save(savePath);
- }
- num++;
- filename.clear();
- }else if (mime.name().startsWith("video/")) {
- capture->open(filename.toLatin1().data());
- if (!capture->isOpened()){
- ui->txt_message->append("fail to open MP4!");
- return;
- }
- IsDetect_ok +=1;
- // if (IsDetect_ok ==2)
- // ui->startdetect->setEnabled(true);
- ui->txt_message->append(QString::fromUtf8("Open video: %1 succesfully!").arg(filename));
-
- //获取整个帧数QStringLiteral
- long totalFrame = capture->get(cv::CAP_PROP_FRAME_COUNT);
- int width = capture->get(cv::CAP_PROP_FRAME_WIDTH);
- int height = capture->get(cv::CAP_PROP_FRAME_HEIGHT);
- ui->txt_message->append(QStringLiteral("整个视频共 %1 帧, 宽=%2 高=%3 ").arg(totalFrame).arg(width).arg(height));
- ui->lbl_res_pic->resize(QSize(width, height));
-
- //设置开始帧()
- long frameToStart = 0;
- capture->set(cv::CAP_PROP_POS_FRAMES, frameToStart);
- ui->txt_message->append(QStringLiteral("从第 %1 帧开始读").arg(frameToStart));
-
- //获取帧率
- double rate = capture->get(cv::CAP_PROP_FPS);
- ui->txt_message->append(QStringLiteral("帧率为: %1 ").arg(rate));
- }
- }
-
- void MainWidget::on_pbn_load_model_clicked()
- {
- QString filePath = QFileDialog::getOpenFileName(this,QStringLiteral("打开文件"),"/home/joe/onnx","*.onnx");
- if(!QFile::exists(filePath)){
- return;
- }
- string model_path=filePath.toStdString();
-
- if (yolov5.readModel(net, model_path, true)) {
- ui->txt_message->append("模型加载成功");
- //提取文件名并显示在TextEdit上
- QFileInfo fileInfo(filePath);
- QString fileName=fileInfo.fileName();
- ui->fileName_tet->setText(fileName);
- ui->fileName_tet->show();
- ui->openfile->setEnabled(true);
- ui->pbn_start_grab->setEnabled(true);
-
- }
- else
- {
- ui->txt_message->append("模型加载失败");
- }
-
- }
-
- //获取图像信息
- void MainWidget::getPtr()
- {
- // 触发模式标记一下,切换触发模式时先执行停止采集图像函数
- m_bContinueStarted = 1;
-
- if (m_nTriggerMode == TRIGGER_ON) {
- // 开始采集之后才创建workthread线程
-
- //开启相机采集
- m_pcMyMainCamera[0]->StartGrabbing();
- int camera_Index=0;
- if (camera_Index == 0) {
- myThread_Camera_Mainshow->getCameraPtr(
- m_pcMyMainCamera[0]); //线程获取左相机指针
- myThread_Camera_Mainshow->getImagePtr(
- myImage_Main); //线程获取图像指针
- myThread_Camera_Mainshow->getCameraIndex(0); //相机 Index==0
-
- if (!myThread_Camera_Mainshow->isRunning()) {
- myThread_Camera_Mainshow->start();
- m_pcMyMainCamera[0]->softTrigger();
- m_pcMyMainCamera[0]->ReadBuffer(*myImage_Main); //读取Mat格式的图像
- }
- }
- }
- }
- //在主界面显示
- void MainWidget::display_myImage_Main(const Mat *imagePrt)
- {
-
-
- cv::Mat rgb;
- cv::cvtColor(*imagePrt, rgb, CV_BGR2RGB);
-
- QImage QmyImage_L;
- QmyImage_L = QImage((const unsigned char *)(rgb.data), rgb.cols,
- rgb.rows, QImage::Format_RGB888);
-
- QmyImage_L = (QmyImage_L)
- .scaled(ui->lbl_res_pic->size(), Qt::IgnoreAspectRatio,
- Qt::SmoothTransformation); //饱满填充
- //显示图像
- //ui->lbl_camera_L->setPixmap(QPixmap::fromImage(QmyImage_L));
- ui->lbl_res_pic->setPixmap(QPixmap::fromImage(QmyImage_L));
- }
-
- void MainWidget::on_startdetect_clicked()
- {
- timer->start();
- // ui->startdetect->setEnabled(false);
- // ui->stopdetect->setEnabled(true);
- ui->openfile->setEnabled(false);
- ui->pbn_load_model->setEnabled(false);
- // ui->cbx_modelName->setEnabled(false);
- ui->txt_message->append(QStringLiteral("=======================\n"
- " 开始检测\n"
- "=======================\n"));
- }
-
- void MainWidget::on_stopdetect_clicked()
- {
- // ui->startdetect->setEnabled(true);
- // ui->stopdetect->setEnabled(false);
- ui->openfile->setEnabled(true);
- ui->pbn_load_model->setEnabled(true);
- // ui->cbx_modelName->setEnabled(true);
- timer->stop();
- ui->txt_message->append(QStringLiteral("======================\n"
- " 停止检测\n"
- "======================\n"));
- }
-
-
- void MainWidget::on_cbx_modelName_activated(const QString &arg1)
- {
-
- }
-
-
-
- void MainWidget::on_checkBox_stateChanged(int arg1)
- {
- if(ui->checkBox->isChecked())
- {
- ui->txt_message->append("您选择了保存结果,保存路径为/home/joe/program/VersionDetect/LiteTest/res_img");
- }
- }
- #include "MvCamera.h"
- #include <stdio.h>
-
- CMvCamera::CMvCamera()
- {
- m_hDevHandle = MV_NULL;
- }
-
- CMvCamera::~CMvCamera()
- {
- if (m_hDevHandle) {
- MV_CC_DestroyHandle(m_hDevHandle);
- m_hDevHandle = MV_NULL;
- }
- }
-
- // ch:获取SDK版本号 | en:Get SDK Version
- int CMvCamera::GetSDKVersion()
- {
- return MV_CC_GetSDKVersion();
- }
-
- // ch:枚举设备 | en:Enumerate Device
- int CMvCamera::EnumDevices(unsigned int nTLayerType,
- MV_CC_DEVICE_INFO_LIST *pstDevList)
- {
- return MV_CC_EnumDevices(nTLayerType, pstDevList);
- }
-
- // ch:判断设备是否可达 | en:Is the device accessible
- bool CMvCamera::IsDeviceAccessible(MV_CC_DEVICE_INFO *pstDevInfo,
- unsigned int nAccessMode)
- {
- return MV_CC_IsDeviceAccessible(pstDevInfo, nAccessMode);
- }
-
- // ch:打开设备 | en:Open Device
- int CMvCamera::Open(MV_CC_DEVICE_INFO *pstDeviceInfo)
- {
- if (MV_NULL == pstDeviceInfo) {
- return MV_E_PARAMETER;
- }
-
- if (m_hDevHandle) {
- return MV_E_CALLORDER;
- }
-
- int nRet = MV_CC_CreateHandle(&m_hDevHandle, pstDeviceInfo);
- if (MV_OK != nRet) {
- return nRet;
- }
-
- nRet = MV_CC_OpenDevice(m_hDevHandle);
- if (MV_OK != nRet) {
- MV_CC_DestroyHandle(m_hDevHandle);
- m_hDevHandle = MV_NULL;
- }
-
- return nRet;
- }
-
- // ch:关闭设备 | en:Close Device
- int CMvCamera::Close()
- {
- if (MV_NULL == m_hDevHandle) {
- return MV_E_HANDLE;
- }
-
- MV_CC_CloseDevice(m_hDevHandle);
-
- int nRet = MV_CC_DestroyHandle(m_hDevHandle);
- m_hDevHandle = MV_NULL;
-
- return nRet;
- }
-
- // ch:判断相机是否处于连接状态 | en:Is The Device Connected
- bool CMvCamera::IsDeviceConnected()
- {
- return MV_CC_IsDeviceConnected(m_hDevHandle);
- }
-
- // ch:注册图像数据回调 | en:Register Image Data CallBack
- int CMvCamera::RegisterImageCallBack(
- void(__stdcall *cbOutput)(unsigned char *pData,
- MV_FRAME_OUT_INFO_EX *pFrameInfo, void *pUser),
- void *pUser)
- {
- return MV_CC_RegisterImageCallBackEx(m_hDevHandle, cbOutput, pUser);
- }
-
- // ch:开启抓图 | en:Start Grabbing
- int CMvCamera::StartGrabbing()
- {
- return MV_CC_StartGrabbing(m_hDevHandle);
- }
-
- // ch:停止抓图 | en:Stop Grabbing
- int CMvCamera::StopGrabbing()
- {
- return MV_CC_StopGrabbing(m_hDevHandle);
- }
-
- // ch:主动获取一帧图像数据 | en:Get one frame initiatively
- int CMvCamera::GetImageBuffer(MV_FRAME_OUT *pFrame, int nMsec)
- {
- return MV_CC_GetImageBuffer(m_hDevHandle, pFrame, nMsec);
- }
-
- // ch:释放图像缓存 | en:Free image buffer
- int CMvCamera::FreeImageBuffer(MV_FRAME_OUT *pFrame)
- {
- return MV_CC_FreeImageBuffer(m_hDevHandle, pFrame);
- }
-
- // ch:主动获取一帧图像数据 | en:Get one frame initiatively
- int CMvCamera::GetOneFrameTimeout(unsigned char *pData, unsigned int *pnDataLen,
- unsigned int nDataSize,
- MV_FRAME_OUT_INFO_EX *pFrameInfo, int nMsec)
- {
- if (NULL == pnDataLen) {
- return MV_E_PARAMETER;
- }
-
- int nRet = MV_OK;
-
- *pnDataLen = 0;
- nRet = MV_CC_GetOneFrameTimeout(m_hDevHandle, pData, nDataSize, pFrameInfo,
- nMsec);
- if (MV_OK != nRet) {
- return nRet;
- }
-
- *pnDataLen = pFrameInfo->nFrameLen;
- return nRet;
- }
-
- // ch:设置显示窗口句柄 | en:Set Display Window Handle
- int CMvCamera::DisplayOneFrame(MV_DISPLAY_FRAME_INFO *pDisplayInfo)
- {
- return MV_CC_DisplayOneFrame(m_hDevHandle, pDisplayInfo);
- }
-
- // ch:设置SDK内部图像缓存节点个数 | en:Set the number of the internal image
- // cache nodes in SDK
- int CMvCamera::SetImageNodeNum(unsigned int nNum)
- {
- return MV_CC_SetImageNodeNum(m_hDevHandle, nNum);
- }
-
- // ch:获取设备信息 | en:Get device information
- int CMvCamera::GetDeviceInfo(MV_CC_DEVICE_INFO *pstDevInfo)
- {
- return MV_CC_GetDeviceInfo(m_hDevHandle, pstDevInfo);
- }
-
- // ch:获取GEV相机的统计信息 | en:Get detect info of GEV camera
- int CMvCamera::GetGevAllMatchInfo(MV_MATCH_INFO_NET_DETECT *pMatchInfoNetDetect)
- {
- if (MV_NULL == pMatchInfoNetDetect) {
- return MV_E_PARAMETER;
- }
-
- MV_CC_DEVICE_INFO stDevInfo = { 0 };
- GetDeviceInfo(&stDevInfo);
- if (stDevInfo.nTLayerType != MV_GIGE_DEVICE) {
- return MV_E_SUPPORT;
- }
-
- MV_ALL_MATCH_INFO struMatchInfo = { 0 };
-
- struMatchInfo.nType = MV_MATCH_TYPE_NET_DETECT;
- struMatchInfo.pInfo = pMatchInfoNetDetect;
- struMatchInfo.nInfoSize = sizeof(MV_MATCH_INFO_NET_DETECT);
- memset(struMatchInfo.pInfo, 0, sizeof(MV_MATCH_INFO_NET_DETECT));
-
- return MV_CC_GetAllMatchInfo(m_hDevHandle, &struMatchInfo);
- }
-
- // ch:获取U3V相机的统计信息 | en:Get detect info of U3V camera
- int CMvCamera::GetU3VAllMatchInfo(MV_MATCH_INFO_USB_DETECT *pMatchInfoUSBDetect)
- {
- if (MV_NULL == pMatchInfoUSBDetect) {
- return MV_E_PARAMETER;
- }
-
- MV_CC_DEVICE_INFO stDevInfo = { 0 };
- GetDeviceInfo(&stDevInfo);
- if (stDevInfo.nTLayerType != MV_USB_DEVICE) {
- return MV_E_SUPPORT;
- }
-
- MV_ALL_MATCH_INFO struMatchInfo = { 0 };
-
- struMatchInfo.nType = MV_MATCH_TYPE_USB_DETECT;
- struMatchInfo.pInfo = pMatchInfoUSBDetect;
- struMatchInfo.nInfoSize = sizeof(MV_MATCH_INFO_USB_DETECT);
- memset(struMatchInfo.pInfo, 0, sizeof(MV_MATCH_INFO_USB_DETECT));
-
- return MV_CC_GetAllMatchInfo(m_hDevHandle, &struMatchInfo);
- }
-
- // ch:获取和设置Int型参数,如 Width和Height,详细内容参考SDK安装目录下的
- // MvCameraNode.xlsx 文件 en:Get Int type parameters, such as Width and Height,
- // for details please refer to MvCameraNode.xlsx file under SDK installation
- // directory
- int CMvCamera::GetIntValue(IN const char *strKey, OUT unsigned int *pnValue)
- {
- if (NULL == strKey || NULL == pnValue) {
- return MV_E_PARAMETER;
- }
-
- MVCC_INTVALUE stParam;
- memset(&stParam, 0, sizeof(MVCC_INTVALUE));
- int nRet = MV_CC_GetIntValue(m_hDevHandle, strKey, &stParam);
- if (MV_OK != nRet) {
- return nRet;
- }
-
- *pnValue = stParam.nCurValue;
- return MV_OK;
- }
-
- int CMvCamera::SetIntValue(IN const char *strKey, IN int64_t nValue)
- {
- return MV_CC_SetIntValueEx(m_hDevHandle, strKey, nValue);
- }
-
- // ch:获取和设置Enum型参数,如 PixelFormat,详细内容参考SDK安装目录下的
- // MvCameraNode.xlsx 文件 en:Get Enum type parameters, such as PixelFormat, for
- // details please refer to MvCameraNode.xlsx file under SDK installation
- // directory
- int CMvCamera::GetEnumValue(IN const char *strKey,
- OUT MVCC_ENUMVALUE *pEnumValue)
- {
- return MV_CC_GetEnumValue(m_hDevHandle, strKey, pEnumValue);
- }
-
- int CMvCamera::SetEnumValue(IN const char *strKey, IN unsigned int nValue)
- {
- return MV_CC_SetEnumValue(m_hDevHandle, strKey, nValue);
- }
-
- int CMvCamera::SetEnumValueByString(IN const char *strKey,
- IN const char *sValue)
- {
- return MV_CC_SetEnumValueByString(m_hDevHandle, strKey, sValue);
- }
-
- // ch:获取和设置Float型参数,如 ExposureTime和Gain,详细内容参考SDK安装目录下的
- // MvCameraNode.xlsx 文件 en:Get Float type parameters, such as ExposureTime and
- // Gain, for details please refer to MvCameraNode.xlsx file under SDK
- // installation directory
- int CMvCamera::GetFloatValue(IN const char *strKey,
- OUT MVCC_FLOATVALUE *pFloatValue)
- {
- return MV_CC_GetFloatValue(m_hDevHandle, strKey, pFloatValue);
- }
-
- int CMvCamera::SetFloatValue(IN const char *strKey, IN float fValue)
- {
- return MV_CC_SetFloatValue(m_hDevHandle, strKey, fValue);
- }
-
- // ch:获取和设置Bool型参数,如 ReverseX,详细内容参考SDK安装目录下的
- // MvCameraNode.xlsx 文件 en:Get Bool type parameters, such as ReverseX, for
- // details please refer to MvCameraNode.xlsx file under SDK installation
- // directory
- int CMvCamera::GetBoolValue(IN const char *strKey, OUT bool *pbValue)
- {
- return MV_CC_GetBoolValue(m_hDevHandle, strKey, pbValue);
- }
-
- int CMvCamera::SetBoolValue(IN const char *strKey, IN bool bValue)
- {
- return MV_CC_SetBoolValue(m_hDevHandle, strKey, bValue);
- }
-
- // ch:获取和设置String型参数,如 DeviceUserID,详细内容参考SDK安装目录下的
- // MvCameraNode.xlsx 文件UserSetSave en:Get String type parameters, such as
- // DeviceUserID, for details please refer to MvCameraNode.xlsx file under SDK
- // installation directory
- int CMvCamera::GetStringValue(IN const char *strKey,
- MVCC_STRINGVALUE *pStringValue)
- {
- return MV_CC_GetStringValue(m_hDevHandle, strKey, pStringValue);
- }
-
- int CMvCamera::SetStringValue(IN const char *strKey, IN const char *strValue)
- {
- return MV_CC_SetStringValue(m_hDevHandle, strKey, strValue);
- }
-
- // ch:执行一次Command型命令,如 UserSetSave,详细内容参考SDK安装目录下的
- // MvCameraNode.xlsx 文件 en:Execute Command once, such as UserSetSave, for
- // details please refer to MvCameraNode.xlsx file under SDK installation
- // directory
- int CMvCamera::CommandExecute(IN const char *strKey)
- {
- return MV_CC_SetCommandValue(m_hDevHandle, strKey);
- }
-
- // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal
- // package size(It only works for the GigE camera)
- int CMvCamera::GetOptimalPacketSize(unsigned int *pOptimalPacketSize)
- {
- if (MV_NULL == pOptimalPacketSize) {
- return MV_E_PARAMETER;
- }
-
- int nRet = MV_CC_GetOptimalPacketSize(m_hDevHandle);
- if (nRet < MV_OK) {
- return nRet;
- }
-
- *pOptimalPacketSize = (unsigned int)nRet;
- return MV_OK;
- }
-
- // ch:注册消息异常回调 | en:Register Message Exception CallBack
- int CMvCamera::RegisterExceptionCallBack(
- void(__stdcall *cbException)(unsigned int nMsgType, void *pUser),
- void *pUser)
- {
- return MV_CC_RegisterExceptionCallBack(m_hDevHandle, cbException, pUser);
- }
-
- // ch:注册单个事件回调 | en:Register Event CallBack
- int CMvCamera::RegisterEventCallBack(
- const char *pEventName,
- void(__stdcall *cbEvent)(MV_EVENT_OUT_INFO *pEventInfo, void *pUser),
- void *pUser)
- {
- return MV_CC_RegisterEventCallBackEx(m_hDevHandle, pEventName, cbEvent,
- pUser);
- }
-
- // ch:强制IP | en:Force IP
- int CMvCamera::ForceIp(unsigned int nIP, unsigned int nSubNetMask,
- unsigned int nDefaultGateWay)
- {
- return MV_GIGE_ForceIpEx(m_hDevHandle, nIP, nSubNetMask, nDefaultGateWay);
- }
-
- // ch:配置IP方式 | en:IP configuration method
- int CMvCamera::SetIpConfig(unsigned int nType)
- {
- return MV_GIGE_SetIpConfig(m_hDevHandle, nType);
- }
-
- // ch:设置网络传输模式 | en:Set Net Transfer Mode
- int CMvCamera::SetNetTransMode(unsigned int nType)
- {
- return MV_GIGE_SetNetTransMode(m_hDevHandle, nType);
- }
-
- // ch:像素格式转换 | en:Pixel format conversion
- int CMvCamera::ConvertPixelType(MV_CC_PIXEL_CONVERT_PARAM *pstCvtParam)
- {
- return MV_CC_ConvertPixelType(m_hDevHandle, pstCvtParam);
- }
-
- // ch:保存图片 | en:save image
- int CMvCamera::SaveImage(MV_SAVE_IMAGE_PARAM_EX *pstParam)
- {
- return MV_CC_SaveImageEx2(m_hDevHandle, pstParam);
- }
-
- //ch:保存图片为文件 | en:Save the image as a file
- // int CMvCamera::SaveImageToFile(MV_SAVE_IMG_TO_FILE_PARAM *pstSaveFileParam)
- //{
- // return MV_CC_SaveImageToFile(m_hDevHandle, pstSaveFileParam);
- //}
-
- //设置是否为触发模式
- int CMvCamera::setTriggerMode(unsigned int TriggerModeNum)
- {
- // 0:Off 1:On
- int tempValue =
- MV_CC_SetEnumValue(m_hDevHandle, "TriggerMode", TriggerModeNum);
- if (tempValue != 0) {
- return -1;
- } else {
- return 0;
- }
- }
-
- //设置触发源
- int CMvCamera::setTriggerSource(unsigned int TriggerSourceNum)
- {
- // 0:Line0 1:Line1 7:Software
- int tempValue =
- MV_CC_SetEnumValue(m_hDevHandle, "TriggerSource", TriggerSourceNum);
- if (tempValue != 0) {
- return -1;
- } else {
- return 0;
- }
- }
-
- //发送软触发
- int CMvCamera::softTrigger()
- {
- int tempValue = MV_CC_SetCommandValue(m_hDevHandle, "TriggerSoftware");
- if (tempValue != 0) {
- return -1;
- } else {
- return 0;
- }
- }
-
- //读取相机中的图像
- // int ReadBuffer(cv::Mat &image);
- int CMvCamera::ReadBuffer(cv::Mat &image)
- {
- cv::Mat *getImage = new cv::Mat();
- unsigned int nRecvBufSize = 0;
- MVCC_INTVALUE stParam;
- memset(&stParam, 0, sizeof(MVCC_INTVALUE));
- int tempValue = MV_CC_GetIntValue(m_hDevHandle, "PayloadSize", &stParam);
- if (tempValue != 0) {
- return -1;
- }
- nRecvBufSize = stParam.nCurValue;
- unsigned char *pDate;
- pDate = (unsigned char *)malloc(nRecvBufSize);
-
- MV_FRAME_OUT_INFO_EX stImageInfo = { 0 };
- tempValue = MV_CC_GetOneFrameTimeout(m_hDevHandle, pDate, nRecvBufSize,
- &stImageInfo, 500);
- if (tempValue != 0) {
- return -1;
- }
- m_nBufSizeForSaveImage =
- stImageInfo.nWidth * stImageInfo.nHeight * 3 + 2048;
- unsigned char *m_pBufForSaveImage;
- m_pBufForSaveImage = (unsigned char *)malloc(m_nBufSizeForSaveImage);
-
- bool isMono;
- switch (stImageInfo.enPixelType) {
- case PixelType_Gvsp_Mono8:
- case PixelType_Gvsp_Mono10:
- case PixelType_Gvsp_Mono10_Packed:
- case PixelType_Gvsp_Mono12:
- case PixelType_Gvsp_Mono12_Packed:
- isMono = true;
- break;
- default:
- isMono = false;
- break;
- }
- if (isMono) {
- *getImage =
- cv::Mat(stImageInfo.nHeight, stImageInfo.nWidth, CV_8UC1, pDate);
- // imwrite("d:\\测试opencv_Mono.tif", image);
- } else {
- //转换图像格式为BGR8
- MV_CC_PIXEL_CONVERT_PARAM stConvertParam = { 0 };
- memset(&stConvertParam, 0, sizeof(MV_CC_PIXEL_CONVERT_PARAM));
- stConvertParam.nWidth = stImageInfo.nWidth; // ch:图像宽 | en:image
- // width
- stConvertParam.nHeight =
- stImageInfo.nHeight; // ch:图像高 | en:image height
- // stConvertParam.pSrcData = m_pBufForDriver; //ch:输入数据缓存 |
- // en:input data buffer
- stConvertParam.pSrcData =
- pDate; // ch:输入数据缓存 | en:input data buffer
- stConvertParam.nSrcDataLen =
- stImageInfo.nFrameLen; // ch:输入数据大小 | en:input data size
- stConvertParam.enSrcPixelType =
- stImageInfo.enPixelType; // ch:输入像素格式 | en:input pixel format
- stConvertParam.enDstPixelType =
- PixelType_Gvsp_BGR8_Packed; // ch:输出像素格式 | en:output pixel
- // format 适用于OPENCV的图像格式
- // stConvertParam.enDstPixelType = PixelType_Gvsp_RGB8_Packed;
- //输出像素格式 | en:output pixel format
- stConvertParam.pDstBuffer =
- m_pBufForSaveImage; // ch:输出数据缓存 | en:output data buffer
- stConvertParam.nDstBufferSize =
- m_nBufSizeForSaveImage; // ch:输出缓存大小 | en:output buffer size
- MV_CC_ConvertPixelType(m_hDevHandle, &stConvertParam);
-
- *getImage = cv::Mat(stImageInfo.nHeight, stImageInfo.nWidth, CV_8UC3,
- m_pBufForSaveImage);
- }
- (*getImage).copyTo(image);
- (*getImage).release();
- free(pDate);
- free(m_pBufForSaveImage);
- return 0;
- }
-
-
- //设置曝光时间
- int CMvCamera::setExposureTime(float ExposureTimeNum)
- {
- int tempValue =
- MV_CC_SetFloatValue(m_hDevHandle, "ExposureTime", ExposureTimeNum);
- if (tempValue != 0) {
- return -1;
- } else {
- return 0;
- }
- }
- #include "mythread.h"
-
- MyThread::MyThread()
- {
- }
-
- MyThread::~MyThread()
- {
- terminate();
- if (cameraPtr != NULL) {
- delete cameraPtr;
- }
- if (imagePtr != NULL) {
- delete imagePtr;
- }
- }
-
- void MyThread::getCameraPtr(CMvCamera *camera)
- {
- cameraPtr = camera;
- }
-
- void MyThread::getImagePtr(Mat *image)
- {
- imagePtr = image;
- }
-
- void MyThread::getCameraIndex(int index)
- {
- cameraIndex = index;
- }
-
- void MyThread::run()
- {
- if (cameraPtr == NULL) {
- return;
- }
-
- if (imagePtr == NULL) {
- return;
- }
-
-
- while (!isInterruptionRequested()) {
- std::cout << "Thread_Trigger:" << cameraPtr->softTrigger() << std::endl;
- std::cout << "Thread_Readbuffer:" << cameraPtr->ReadBuffer(*imagePtr)
- << std::endl;
- //cameraPtr->ReadBuffer(*imagePtr2);
- emit mess();
- emit Display(imagePtr); //发送信号lbl_camera_L接收并显示
-
- emit GetPtr(imagePtr); //发送信号yolo进行检测并显示
-
-
- msleep(30);
- }
- }
-
- #include "widget.h"
- #include "./ui_widget.h"
-
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <fstream>
- #include <iostream>
- #include <QDebug>
-
- Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
- {
- ui->setupUi(this);
- ui->lbl_camera_L->setPixmap(QPixmap(":/icon/MVS.png"));
- ui->lbl_camera_L->setScaledContents(true);
-
- //ui->lbl_camera_R->setPixmap(QPixmap("back_img.jpg"));
- //ui->lbl_camera_R->setScaledContents(true);
-
- // 相机初始化控件
- ui->pbn_enum_camera->setEnabled(true);
- ui->pbn_open_camera->setEnabled(false);
- ui->pbn_close_camera->setEnabled(false);
- ui->cmb_camera_index->setEnabled(false);
-
- // 图像采集控件
- ui->rdo_continue_mode->setEnabled(false);
- ui->rdo_softigger_mode->setEnabled(false);
- ui->pbn_start_grabbing->setEnabled(false);
- ui->pbn_stop_grabbing->setEnabled(false);
- ui->pbn_software_once->setEnabled(false);
-
- // 参数控件
- ui->le_set_exposure->setEnabled(false);
- ui->le_set_gain->setEnabled(false);
-
- // 保存图像控件
- ui->pbn_save_BMP->setEnabled(false);
- ui->pbn_save_JPG->setEnabled(false);
-
- // 线程对象实例化
- myThread_Camera_show = new MyThread; //相机线程对象
-
-
- //发送信号实现页面切换
- connect(ui->pbn_return_main,SIGNAL(clicked()),this,SIGNAL(back()));
-
- connect(myThread_Camera_show, SIGNAL(Display(const Mat *)), this,
- SLOT(display_myImage_L(const Mat *)));
-
-
- // 曝光和增益的输入控件限制值
- QRegExp int_rx("100000|([0-9]{0,5})");
- ui->le_set_exposure->setValidator(new QRegExpValidator(int_rx, this));
- QRegExp double_rx("15|([0-9]{0,1}[0-5]{1,2}[\.][0-9]{0,1})");
- ui->le_set_gain->setValidator(new QRegExpValidator(double_rx, this));
-
-
- }
-
- Widget::~Widget()
- {
- delete ui;
- delete mainWid;
- delete myThread_Camera_show;
- delete myImage_L;
- }
-
- //创建关闭子窗体事件,显示主窗体
- void Widget::closeEvent(QCloseEvent *event)
- {
- emit closedWid(); //发射closed信号
- event->accept();
-
- }
-
-
- void Widget::on_pbn_enum_camera_clicked()
- {
- memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
- int nRet = MV_OK;
- nRet = CMvCamera::EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &m_stDevList);
-
- devices_num = m_stDevList.nDeviceNum;
- if (devices_num == 0) {
- QString cameraInfo;
- cameraInfo =
- QString::fromLocal8Bit("暂无设备可连接,请检查设备是否连接正确!");
- ui->lbl_camera_messagee->setText(cameraInfo);
- }
- if (devices_num > 0) {
- QString cameraInfo;
- for (int i = 0; i < devices_num; i++) {
- MV_CC_DEVICE_INFO *pDeviceInfo = m_stDevList.pDeviceInfo[i];
- QString cameraInfo_i = PrintDeviceInfo(pDeviceInfo, i);
- cameraInfo.append(cameraInfo_i);
- cameraInfo.append("\n");
- ui->cmb_camera_index->addItem(QString::number(i+1));
- }
- ui->lbl_camera_messagee->setText(cameraInfo);
- ui->pbn_open_camera->setEnabled(true);
- ui->cmb_camera_index->setEnabled(true);
- }
- }
-
- //打印相机的型号、ip等信息
- QString Widget::PrintDeviceInfo(MV_CC_DEVICE_INFO *pstMVDevInfo, int num_index)
- {
- QString cameraInfo_index;
- cameraInfo_index = QString::fromLocal8Bit("相机序号:");
- cameraInfo_index.append(QString::number(num_index+1));
- cameraInfo_index.append("\t\t");
- // 海康GIGE协议的相机
- if (pstMVDevInfo->nTLayerType == MV_GIGE_DEVICE) {
- int nIp1 =
- ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >>
- 24);
- int nIp2 =
- ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >>
- 16);
- int nIp3 =
- ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >>
- 8);
- int nIp4 =
- (pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff);
-
- cameraInfo_index.append(QString::fromLocal8Bit("相机型号:"));
- std::string str_name =
- (char *)pstMVDevInfo->SpecialInfo.stGigEInfo.chModelName;
- cameraInfo_index.append(QString::fromStdString(str_name));
- cameraInfo_index.append("\n");
- cameraInfo_index.append(QString::fromLocal8Bit("当前相机IP地址:"));
- cameraInfo_index.append(QString::number(nIp1));
- cameraInfo_index.append(".");
- cameraInfo_index.append(QString::number(nIp2));
- cameraInfo_index.append(".");
- cameraInfo_index.append(QString::number(nIp3));
- cameraInfo_index.append(".");
- cameraInfo_index.append(QString::number(nIp4));
- cameraInfo_index.append("\t");
- } else if (pstMVDevInfo->nTLayerType == MV_USB_DEVICE) {
- cameraInfo_index.append(QString::fromLocal8Bit("相机型号:"));
- std::string str_name =
- (char *)pstMVDevInfo->SpecialInfo.stUsb3VInfo.chModelName;
- cameraInfo_index.append(QString::fromStdString(str_name));
- cameraInfo_index.append("\n");
- } else {
- cameraInfo_index.append(QString::fromLocal8Bit("相机型号:未知"));
- }
- cameraInfo_index.append(QString::fromLocal8Bit("相机品牌:海康威视"));
- return cameraInfo_index;
- }
-
- void Widget::on_pbn_open_camera_clicked()
- {
- ui->pbn_open_camera->setEnabled(false);
- ui->pbn_close_camera->setEnabled(true);
- ui->rdo_continue_mode->setEnabled(true);
- ui->rdo_softigger_mode->setEnabled(true);
-
- ui->rdo_continue_mode->setCheckable(true);
- // 参数据控件
- ui->le_set_exposure->setEnabled(true);
- ui->le_set_gain->setEnabled(true);
-
-
- OpenDevices();
- }
-
- void Widget::OpenDevices()
- {
- int nRet = MV_OK;
- // 创建相机指针对象
- for (unsigned int i = 0, j = 0; j < m_stDevList.nDeviceNum; j++, i++) {
- m_pcMyCamera[i] = new CMvCamera;
- // 相机对象初始化
- m_pcMyCamera[i]->m_pBufForDriver = NULL;
- m_pcMyCamera[i]->m_pBufForSaveImage = NULL;
- m_pcMyCamera[i]->m_nBufSizeForDriver = 0;
- m_pcMyCamera[i]->m_nBufSizeForSaveImage = 0;
- m_pcMyCamera[i]->m_nTLayerType =
- m_stDevList.pDeviceInfo[j]->nTLayerType;
-
- nRet = m_pcMyCamera[i]->Open(m_stDevList.pDeviceInfo[j]); //打开相机
- //设置触发模式
- m_pcMyCamera[i]->setTriggerMode(TRIGGER_ON);
- //设置触发源为软触发
- m_pcMyCamera[i]->setTriggerSource(TRIGGER_SOURCE);
- //设置曝光时间,初始为40000,并关闭自动曝光模式
- m_pcMyCamera[i]->setExposureTime(EXPOSURE_TIME);
- m_pcMyCamera[i]->SetEnumValue("ExposureAuto",
- MV_EXPOSURE_AUTO_MODE_OFF);
- }
- }
-
- void Widget::on_rdo_continue_mode_clicked()
- {
- ui->pbn_start_grabbing->setEnabled(true);
- m_nTriggerMode = TRIGGER_ON;
- }
-
- void Widget::on_rdo_softigger_mode_clicked()
- {
- // 如果开始选择的连续模式,切换到触发模式之前,需要先停止采集
- if (m_bContinueStarted == 1) {
- on_pbn_stop_grabbing_clicked(); //先执行停止采集
- }
-
- ui->pbn_start_grabbing->setEnabled(false);
- ui->pbn_software_once->setEnabled(true);
-
- m_nTriggerMode = TRIGGER_OFF;
- for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++) {
- m_pcMyCamera[i]->setTriggerMode(m_nTriggerMode);
- }
- }
-
- void Widget::on_pbn_start_grabbing_clicked()
- {
- // 触发模式标记一下,切换触发模式时先执行停止采集图像函数
- m_bContinueStarted = 1;
-
- ui->pbn_start_grabbing->setEnabled(false);
- ui->pbn_stop_grabbing->setEnabled(true);
- // 保存图像控件
- ui->pbn_save_BMP->setEnabled(true);
- // 图像采集控件
- ui->pbn_save_JPG->setEnabled(true);
-
- int camera_Index = 0;
-
- // 先判断什么模式,再判断是否正在采集
- if (m_nTriggerMode == TRIGGER_ON) {
- // 开始采集之后才创建workthread线程
- for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++) {
- //开启相机采集
- m_pcMyCamera[i]->StartGrabbing();
- camera_Index = i;
- if (camera_Index == 0) {
- myThread_Camera_show->getCameraPtr(
- m_pcMyCamera[0]); //线程获取左相机指针
- myThread_Camera_show->getImagePtr(
- myImage_L); //线程获取图像指针
- myThread_Camera_show->getCameraIndex(0); //相机 Index==0
-
- if (!myThread_Camera_show->isRunning()) {
- myThread_Camera_show->start();
- m_pcMyCamera[0]->softTrigger();
- m_pcMyCamera[0]->ReadBuffer(*myImage_L); //读取Mat格式的图像
- }
- }
- }
- }
- }
-
- void Widget::on_pbn_stop_grabbing_clicked()
- {
- ui->pbn_start_grabbing->setEnabled(true);
- ui->pbn_stop_grabbing->setEnabled(false);
-
- for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++) {
- //关闭相机
- if (myThread_Camera_show->isRunning()) {
- m_pcMyCamera[0]->StopGrabbing();
- myThread_Camera_show->requestInterruption();
- myThread_Camera_show->wait();
- }
- }
- }
-
- void Widget::on_pbn_software_once_clicked()
- {
- // 保存图像控件
- ui->pbn_save_BMP->setEnabled(true);
- ui->pbn_save_JPG->setEnabled(true);
-
- if (m_nTriggerMode == TRIGGER_OFF) {
- int nRet = MV_OK;
- for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++) {
- //开启相机采集
- m_pcMyCamera[i]->StartGrabbing();
-
- if (i == 0) {
- nRet = m_pcMyCamera[i]->CommandExecute("TriggerSoftware");
- m_pcMyCamera[i]->ReadBuffer(*myImage_L);
- display_myImage_L(myImage_L); //左相机图像
- display_myImage_Main(myImage_L); //主界面显示
- }
- }
- }
- }
-
- //在相机配置界面显示
- void Widget::display_myImage_L(const Mat *imagePrt)
- {
-
- cv::Mat rgb;
-
- //判断是黑白、彩色图像
- QImage QmyImage_L;
- if (myImage_L->channels() > 1) {
- cv::cvtColor(*imagePrt, rgb, CV_BGR2RGB);
- QmyImage_L = QImage((const unsigned char *)(rgb.data), rgb.cols,
- rgb.rows, QImage::Format_RGB888);
- } else {
- cv::cvtColor(*imagePrt, rgb, CV_GRAY2RGB);
- QmyImage_L = QImage((const unsigned char *)(rgb.data), rgb.cols,
- rgb.rows, QImage::Format_RGB888);
- }
-
-
- QmyImage_L = (QmyImage_L)
- .scaled(ui->lbl_camera_L->size(), Qt::IgnoreAspectRatio,
- Qt::SmoothTransformation); //饱满填充
-
- ui->lbl_camera_L->setPixmap(QPixmap::fromImage(QmyImage_L));
-
- }
-
- //在主界面显示
- void Widget::display_myImage_Main(const Mat *imagePrt)
- {
- cv::Mat rgb;
- cv::cvtColor(*imagePrt, rgb, CV_BGR2RGB);
-
- QImage QmyImage_L;
- QmyImage_L = QImage((const unsigned char *)(rgb.data), rgb.cols,
- rgb.rows, QImage::Format_RGB888);
-
- QmyImage_L = (QmyImage_L)
- .scaled(ui->lbl_camera_L->size(), Qt::IgnoreAspectRatio,
- Qt::SmoothTransformation); //饱满填充
- QDateTime curdatetime;
- if(!QmyImage_L.isNull()){
- curdatetime=QDateTime::currentDateTime();
- QString str=curdatetime.toString("yyyyMMddhhmmss");
- QString filename="/home/joe/picture/"+str+".png";
- qDebug()<<"正在保存"<<filename<<"图片,请稍候...";
- /* save(arg1,arg2,arg3)重载函数,arg1 代表路径文件名,
- * arg2 保存的类型,arg3 代表保存的质量等级 */
- QmyImage_L.save(filename,"PNG",-1);
- qDebug()<<"保存完成!";
- }
-
- //显示图像
- this->mainWid=new MainWidget();
- //ui->lbl_camera_L->setPixmap(QPixmap::fromImage(QmyImage_L));
- mainWid->ui->lbl_res_pic->setPixmap(QPixmap::fromImage(QmyImage_L));
- }
-
- void Widget::CloseDevices()
- {
- for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++) {
- // 关闭线程、相机
- if (myThread_Camera_show->isRunning()) {
- myThread_Camera_show->requestInterruption();
- myThread_Camera_show->wait();
- m_pcMyCamera[0]->StopGrabbing();
- }
-
- m_pcMyCamera[i]->Close();
- }
-
- // 关闭之后再枚举一遍
- memset(&m_stDevList, 0,
- sizeof(MV_CC_DEVICE_INFO_LIST)); // 初始化设备信息列表
- int devices_num = MV_OK;
- devices_num =
- CMvCamera::EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE,
- &m_stDevList); // 枚举子网内所有设备,相机设备数量
- }
-
- void Widget::on_pbn_close_camera_clicked()
- {
- ui->pbn_open_camera->setEnabled(true);
- ui->pbn_close_camera->setEnabled(false);
- // 图像采集控件
- ui->rdo_continue_mode->setEnabled(false);
- ui->rdo_softigger_mode->setEnabled(false);
- ui->pbn_start_grabbing->setEnabled(false);
- ui->pbn_stop_grabbing->setEnabled(false);
- ui->pbn_software_once->setEnabled(false);
- // 参数控件
- ui->le_set_exposure->setEnabled(false);
- ui->le_set_gain->setEnabled(false);
- // 保存图像控件
- ui->pbn_save_BMP->setEnabled(false);
- ui->pbn_save_JPG->setEnabled(false);
-
- // 关闭设备,销毁线程
- CloseDevices();
- ui->lbl_camera_messagee->clear();
- ui->lbl_camera_L->clear();
- ui->lbl_camera_L->setPixmap(QPixmap(":/icon/MVS.png"));
- //ui->lbl_camera_R->clear();
- }
-
- void Widget::on_pbn_save_BMP_clicked()
- {
- m_nSaveImageType = MV_Image_Bmp;
- SaveImage();
-
- }
-
- void Widget::on_pbn_save_JPG_clicked()
- {
- m_nSaveImageType = MV_Image_Jpeg;
- SaveImage();
- }
-
- void Widget::SaveImage()
- {
- // 获取1张图
- MV_FRAME_OUT_INFO_EX stImageInfo = { 0 };
- memset(&stImageInfo, 0, sizeof(MV_FRAME_OUT_INFO_EX));
- unsigned int nDataLen = 0;
- int nRet = MV_OK;
-
- //保存图片的路径
- QString saveDirPath="/home/joe/program/VersionDetect/LiteTest/image/";
- for (int i = 0; i < devices_num; i++) {
-
- //保存图像的缓存类指针
- const char *imageName_c_str=NULL;
- // 仅在第一次保存图像时申请缓存,在CloseDevice时释放
- if (NULL == m_pcMyCamera[i]->m_pBufForDriver) {
- unsigned int nRecvBufSize = 0;
-
- m_pcMyCamera[i]->GetIntValue("PayloadSize", &nRecvBufSize);
-
- m_pcMyCamera[i]->m_nBufSizeForDriver = nRecvBufSize; // 一帧数据大小
-
- m_pcMyCamera[i]->m_pBufForDriver =
- (unsigned char *)malloc(m_pcMyCamera[i]->m_nBufSizeForDriver);
- }
-
- nRet = m_pcMyCamera[i]->GetOneFrameTimeout(
- m_pcMyCamera[i]->m_pBufForDriver, &nDataLen,
- m_pcMyCamera[i]->m_nBufSizeForDriver, &stImageInfo, 1000);
- if (MV_OK == nRet) {
- // 仅在第一次保存图像时申请缓存,在 CloseDevice 时释放
- if (NULL == m_pcMyCamera[i]->m_pBufForSaveImage) {
- // BMP图片大小:width * height * 3 + 2048(预留BMP头大小)
- m_pcMyCamera[i]->m_nBufSizeForSaveImage =
- stImageInfo.nWidth * stImageInfo.nHeight * 3 + 2048;
-
- m_pcMyCamera[i]->m_pBufForSaveImage = (unsigned char *)malloc(
- m_pcMyCamera[i]->m_nBufSizeForSaveImage);
- }
- // 设置对应的相机参数
- MV_SAVE_IMAGE_PARAM_EX stParam = { 0 };
- stParam.enImageType = m_nSaveImageType; // 需要保存的图像类型
- stParam.enPixelType = stImageInfo.enPixelType; // 相机对应的像素格式
- stParam.nBufferSize =
- m_pcMyCamera[i]->m_nBufSizeForSaveImage; // 存储节点的大小
- stParam.nWidth = stImageInfo.nWidth; // 相机对应的宽
- stParam.nHeight = stImageInfo.nHeight; // 相机对应的高
- stParam.nDataLen = stImageInfo.nFrameLen;
- stParam.pData = m_pcMyCamera[i]->m_pBufForDriver;
- stParam.pImageBuffer = m_pcMyCamera[i]->m_pBufForSaveImage;
- stParam.nJpgQuality = 90; // jpg编码,仅在保存Jpg图像时有效
-
- nRet = m_pcMyCamera[i]->SaveImage(&stParam);
-
-
- QString image_name;
- //图像名称
- char chImageName[IMAGE_NAME_LEN] = {0};
- if (MV_Image_Bmp == stParam.enImageType) {
- if (i == 0) {
- snprintf(chImageName, IMAGE_NAME_LEN,
- "Image_w%d_h%d_fn%d_L.bmp", stImageInfo.nWidth,
- stImageInfo.nHeight, stImageInfo.nFrameNum);
- image_name = "Image_w";
- image_name.append(QString::number(stImageInfo.nWidth));
- image_name.append("_h");
- image_name.append(QString::number(stImageInfo.nHeight));
- image_name.append("_fn");
- image_name.append(QString::number(stImageInfo.nFrameNum));
- image_name.append("_L.bmp");
- }
- if (i == 1) {
- snprintf(chImageName, IMAGE_NAME_LEN,
- "Image_w%d_h%d_fn%03d_R.bmp", stImageInfo.nWidth,
- stImageInfo.nHeight, stImageInfo.nFrameNum);
- }
-
- } else if (MV_Image_Jpeg == stParam.enImageType) {
- if (i == 0) {
- snprintf(chImageName, IMAGE_NAME_LEN,
- "Image_w%d_h%d_fn%d_L.jpg", stImageInfo.nWidth,
- stImageInfo.nHeight, stImageInfo.nFrameNum);
- image_name = "Image_w";
- image_name.append(QString::number(stImageInfo.nWidth));
- image_name.append("_h");
- image_name.append(QString::number(stImageInfo.nHeight));
- image_name.append("_fn");
- image_name.append(QString::number(stImageInfo.nFrameNum));
- image_name.append("_L.jpg");
- }
- if (i == 1) {
- snprintf(chImageName, IMAGE_NAME_LEN,
- "Image_w%d_h%d_fn%03d_R.jpg", stImageInfo.nWidth,
- stImageInfo.nHeight, stImageInfo.nFrameNum);
- }
-
- }
-
- QString imagePath = saveDirPath + image_name;
- QByteArray ba = imagePath.toLatin1();
- imageName_c_str = ba.data();
-
-
- FILE *fp = fopen(imageName_c_str, "wb");
-
- fwrite(m_pcMyCamera[i]->m_pBufForSaveImage, 1, stParam.nImageLen,
- fp);
- fclose(fp);
-
-
- // ui->lbl_camera_R->setPixmap(QPixmap(image_name));
- // ui->lbl_camera_R->setScaledContents(true);
- }
- }
- }
-
-
- void Widget::on_le_set_exposure_textChanged(const QString &arg1)
- {
- //设置曝光时间
- QString str = ui->le_set_exposure->text(); // 读取
- int exposure_Time = str.toInt();
-
- for (int i = 0; i < devices_num; i++) {
- m_pcMyCamera[i]->SetEnumValue("ExposureAuto",
- MV_EXPOSURE_AUTO_MODE_OFF);
- m_pcMyCamera[i]->SetFloatValue("ExposureTime", exposure_Time);
- }
- }
-
- void Widget::on_le_set_gain_textChanged(const QString &arg1)
- {
- QString str = ui->le_set_gain->text(); // 读取
- float gain = str.toFloat();
-
- for (int i = 0; i < devices_num; i++) {
- m_pcMyCamera[i]->SetEnumValue("GainAuto", 0);
- m_pcMyCamera[i]->SetFloatValue("Gain", gain);
- }
- }
-
-
- void Widget::on_pbn_return_main_clicked()
- {
- //发送信号实现页面切换
- //connect(ui->pbn_return_main,SIGNAL(clicked()),this,SIGNAL(back()));
- }
5)yolov5.cpp
- #include"yolov5.h"
- using namespace std;
- using namespace cv;
- using namespace cv::dnn;
-
-
- bool YoloV5::readModel(Net &net, string &netPath,bool isCuda = false) {
- try {
- net = readNetFromONNX(netPath);
- }
- catch (const std::exception&) {
- return false;
- }
- //cuda
- if (isCuda) {
- net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
- net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
- }
- //cpu
- else {
- net.setPreferableBackend(cv::dnn::DNN_BACKEND_DEFAULT);
- net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
- }
- return true;
- }
- bool YoloV5::Detect(Mat &SrcImg,Net &net,vector<Output> &output) {
- Mat blob;
- int col = SrcImg.cols;
- int row = SrcImg.rows;
- int maxLen = MAX(col, row);
- Mat netInputImg = SrcImg.clone();
- if (maxLen > 1.2*col || maxLen > 1.2*row) {
- Mat resizeImg = Mat::zeros(maxLen, maxLen, CV_8UC3);
- SrcImg.copyTo(resizeImg(Rect(0, 0, col, row)));
- netInputImg = resizeImg;
- }
- blobFromImage(netInputImg, blob, 1 / 255.0, cv::Size(netWidth, netHeight), cv::Scalar(104, 117,123), true, false);
- //blobFromImage(netInputImg, blob, 1 / 255.0, cv::Size(netWidth, netHeight), cv::Scalar(0, 0,0), true, false);//如果训练集未对图片进行减去均值操作,则需要设置为这句
- //blobFromImage(netInputImg, blob, 1 / 255.0, cv::Size(netWidth, netHeight), cv::Scalar(114, 114,114), true, false);
- net.setInput(blob);
- std::vector<cv::Mat> netOutputImg;
- // vector<string> outputLayerName{"652","669", "686","output" };
- // net.forward(netOutputImg, outputLayerName[2]); //获取output的输出
- net.forward(netOutputImg, net.getUnconnectedOutLayersNames());
-
- //接上面
- std::vector<int> classIds;//结果id数组
- std::vector<float> confidences;//结果每个id对应置信度数组
- std::vector<cv::Rect> boxes;//每个id矩形框
- float ratio_h = (float)netInputImg.rows / netHeight;
- float ratio_w = (float)netInputImg.cols / netWidth;
- int net_width = className.size() + 5; //输出的网络宽度是类别数+5
- float* pdata = (float*)netOutputImg[0].data;
- for (int stride = 0; stride < 3; stride++) { //stride
- int grid_x = (int)(netWidth / netStride[stride]);
- int grid_y = (int)(netHeight / netStride[stride]);
- for (int anchor = 0; anchor < 3; anchor++) { //anchors
- const float anchor_w = netAnchors[stride][anchor * 2];
- const float anchor_h = netAnchors[stride][anchor * 2 + 1];
- for (int i = 0; i < grid_y; i++) {
- for (int j = 0; j < grid_y; j++) {
- float box_score = Sigmoid(pdata[4]);//获取每一行的box框中含有某个物体的概率
- if (box_score > boxThreshold) {
- //为了使用minMaxLoc(),将85长度数组变成Mat对象
- cv::Mat scores(1,className.size(), CV_32FC1, pdata+5);
- Point classIdPoint;
- double max_class_socre;
- minMaxLoc(scores, 0, &max_class_socre, 0, &classIdPoint);
- max_class_socre = Sigmoid((float)max_class_socre);
- if (max_class_socre > classThreshold) {
- //rect [x,y,w,h]
- float x = (Sigmoid(pdata[0]) * 2.f - 0.5f + j) * netStride[stride]; //x
- float y = (Sigmoid(pdata[1]) * 2.f - 0.5f + i) * netStride[stride]; //y
- float w = powf(Sigmoid(pdata[2]) * 2.f, 2.f) * anchor_w; //w
- float h = powf(Sigmoid(pdata[3]) * 2.f, 2.f) * anchor_h; //h
- int left = (x - 0.5*w)*ratio_w;
- int top = (y - 0.5*h)*ratio_h;
- classIds.push_back(classIdPoint.x);
- confidences.push_back(max_class_socre*box_score);
- boxes.push_back(Rect(left, top, int(w*ratio_w), int(h*ratio_h)));
- }
- }
- pdata += net_width;//指针移到下一行
- }
- }
- }
- }
- vector<int> nms_result;
- NMSBoxes(boxes, confidences, classThreshold, nmsThreshold, nms_result);
- for (int i = 0; i < nms_result.size(); i++) {
- int idx = nms_result[i];
- Output result;
- result.id = classIds[idx];
- result.confidence = confidences[idx];
- result.box = boxes[idx];
- output.push_back(result);
- }
-
- if (output.size())
- return true;
- else
- return false;
- }
-
- //这里的color是颜色数组,对没一个id随机分配一种颜色
- void YoloV5::drawPred(Mat &img, vector<Output> result, vector<Scalar> color) {
- for (int i = 0; i < result.size(); i++) {
- int left, top;
- left = result[i].box.x;
- top = result[i].box.y;
- int color_num = i;
- //rectangle(img, result[i].box, color[result[i].id], 2, 8);
- rectangle(img, result[i].box, Scalar(255, 0, 0), 2, 8);
- string label = className[result[i].id] +":" + to_string(result[i].confidence);
-
- int baseLine;
- Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
- top = max(top, labelSize.height);
- //rectangle(frame, Point(left, top - int(1.5 * labelSize.height)), Point(left + int(1.5 * labelSize.width), top + baseLine), Scalar(0, 255, 0), FILLED);
- //putText(img, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 1, color[result[i].id], 2);
- putText(img, label, Point(30, 100), FONT_HERSHEY_SIMPLEX, 2.5, Scalar(255, 0, 0), 2);
- }
- }
-
- void getTime(QString msg)
- {
- auto start = std::chrono::steady_clock::now();
- auto end = std::chrono::steady_clock::now();
- std::chrono::duration<double, std::milli> elapsed = end - start;
- QString output = msg.arg(elapsed.count());
- string out = output.toStdString();
- cout<<out<<endl;
- }
这里需要讲一下,如果如前面所示你用的单一输出,如下图
要用
outputLayerName来获取数组,如作者的onnx模型,名称为output,那就获取整个output的权重,数据,如果导出格式如下图所示:
那么你就要用
以上的forword函数来获取权重文件,其他地方基本无需改动,当然肯定部署会出现各种报错,在你读懂了代码之后,基本上都能改好
写在最后:如果想要qt源码文件,可以进入以下链接,创作不易,谢谢大家支持
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。