国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于樹莓派Qt+opencv+yolov5-Lite+C++部署深度學(xué)習(xí)推理

這篇具有很好參考價值的文章主要介紹了基于樹莓派Qt+opencv+yolov5-Lite+C++部署深度學(xué)習(xí)推理。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

前言:

? ? ? ? 本文是基于qt和opencv的dnn深度學(xué)習(xí)推理模塊,在樹莓派上部署YOLO系列推理,適用于yolov5-6.1以及yolov5-Lite,相比直接用python的onnxruntime,用基于opencv的dnn模塊,利用訓(xùn)練生成的onnx模型,即可快速部署,不需要在樹莓派上額外安裝深度學(xué)習(xí)的一系列環(huán)境,因為我們知道部署環(huán)境是比較玄學(xué)的,也是比較麻煩的。

? ? ? ? 剛開始使用的是YOLOv5-6.1版本,部署在電腦虛擬機(jī)上能達(dá)到7fps,但是如果在樹莓派上運(yùn)行,速度極慢,基本上fps在0.3左右,即推理一次所需的時間在3s以上,實際上根本達(dá)不到實時的要求。因此,作者換了更輕量化的網(wǎng)絡(luò)yoloV5-Lite,部署完成后fps大概在1.54左。之前看到過有作者直接用onnxruntime推理fps能達(dá)到5左右,可能是因為qt占樹莓派運(yùn)行內(nèi)存較大,故很慢。

? ? ? ? 因此本文首先是使用??倒I(yè)相機(jī)采集到需要的數(shù)據(jù)集,然后在PC端利用YOLOV5-Lite網(wǎng)絡(luò)進(jìn)行訓(xùn)練,訓(xùn)練完成之后,將生成的.pt(pytorch格式)權(quán)重文件轉(zhuǎn)換為.onnx格式,方便后續(xù)利用opencv的dnn模塊直接推理。在得到了onnx權(quán)重文件后,在樹莓派上部署推理所需的環(huán)境,即安裝qt和opencv。配置好環(huán)境后,在qt開發(fā)一個簡單的界面,根據(jù)自己的需求,將所有模塊融合進(jìn)去,最后就可以推理成功啦。話不多說,作者的簡單界面是這樣的。

qt6 深度學(xué)習(xí)部署,qt,opencv,YOLO,深度學(xué)習(xí),c++,linux

下面就開始逐步跟大家講一下實現(xiàn)過程。

一、數(shù)據(jù)集準(zhǔn)備

? ? ? ? 由于作者做的是工業(yè)相關(guān)的一個小項目,基于甲方提供的設(shè)備,數(shù)據(jù)集采集是使用??低暤墓I(yè)相機(jī),后續(xù)實時推理也是連接了海康工業(yè)相機(jī),具體如何在Linux系統(tǒng)下,使用qt成功控制??倒I(yè)相機(jī),鏈接里面有詳細(xì)說明。有些同學(xué)可能使用的是公開的數(shù)據(jù)集,那這節(jié)可以略過。至于給數(shù)據(jù)集打標(biāo)簽以及配置深度學(xué)習(xí)環(huán)境等一系列問題,作者參考的是良心up炮哥,鏈接放下面目標(biāo)檢測---教你利用yolov5訓(xùn)練自己的目標(biāo)檢測模型,此外他還有很多博客,可以從0環(huán)境到實現(xiàn)搭建深度學(xué)習(xí)YOLOv5所需的所有環(huán)境,因為YOLOV5-Lite和YOLOV5所需的環(huán)境是一樣的,所以可以直接拿來用。

二、訓(xùn)練模型

? ? ? ? 訓(xùn)練模型過程中,都是常用的參數(shù)更改,根據(jù)自己的數(shù)據(jù)集路徑,更改yaml文件等操作,這里不再贅述,上節(jié)鏈接中作者的博客中都有,觸類旁通,yolov5-Lite也是一樣的。訓(xùn)練完成后可以發(fā)現(xiàn)在train文件夾下exp...某個文件夾中生成了best.pt和last.pt,使用best.pt就可以轉(zhuǎn)換為onnx格式啦。

三、.pt轉(zhuǎn)onnx

? ? ? ? 這一步是至關(guān)重要的,直接關(guān)乎到是否能推理成功。至于如何轉(zhuǎn)onnx,yolov5作者都有寫,運(yùn)行export.py就可以轉(zhuǎn)換成功。

? ? ? ? 作者的代碼適用于推理YOLOv5-6.1或者onnx輸出后整合為單一通道的格式,如下圖,其中output就是將三個尺度,也就是80,40,20整合為一個輸出,方便后續(xù)推理的時候讀取。

qt6 深度學(xué)習(xí)部署,qt,opencv,YOLO,深度學(xué)習(xí),c++,linux

?當(dāng)然,也可以使用下圖中的格式,只是需要在推理的時候改一下代碼,后續(xù)會講到

qt6 深度學(xué)習(xí)部署,qt,opencv,YOLO,深度學(xué)習(xí),c++,linux

?四、樹莓派部署qt和opencv環(huán)境

(1)安裝qt5

????????對于樹莓派安裝qt,可以參考以下博客,還是比較簡單的,具體可以搜一下教程,基本都可以成功,但是要注意,qt在5.14版本以后變成了online安裝,也就是線上安裝,因此樹莓派必須成功聯(lián)網(wǎng),不然安裝不上,作者安裝的qt版本是5.14.2。

(2)安裝opencv

????????安裝opencv可以說是很玄學(xué)的,你是天選之子,那一次就可以成功,但作者并非是,在樹莓派配置opencv環(huán)境過程中,足足花費(fèi)了一下午時間,一直在處理報錯的路上,作者也整理了一下如何在Linux下配置opencv,下面就細(xì)細(xì)講解一下。

? ??????1)下載opencv4.7.0壓縮包

????????https://opencv.org/releases.html,找到對應(yīng)的版本安裝,但注意,opencv4.5以上版本才支持dnn推理,也就是深度學(xué)習(xí)模型的讀取,不能安裝低于4.5的版本。

????????2)安裝前準(zhǔn)備

? ? ? ? 在下載好了壓縮包后,右鍵提取到當(dāng)前目錄下,然后進(jìn)入opencv4.7.0

目錄中,并在opencv-4.7.0下創(chuàng)建鍵build和install兩個文件夾,后續(xù)編譯會用到。

? ? ? ? 下面就是安裝CmakeCmake-gui以及所依賴的庫(若出錯可以思考一下是否執(zhí)行了sudo apt updatesudo apt upgrade),執(zhí)行如下代碼

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
????????3)開始安裝?

? ? ? ? ? ? 進(jìn)入build文件夾下編譯cmake?,執(zhí)行命令

cmake-gui

打開了cmake-gui圖形化界面,需要更改的地方如下圖所示

qt6 深度學(xué)習(xí)部署,qt,opencv,YOLO,深度學(xué)習(xí),c++,linux

首先,1是我們解壓好的opencv安裝包的路徑,2處選擇build文件夾的路徑?,記得一定要勾選3處Advanced。然后就可以點(diǎn)擊configure開始配置了。在configure done之后,我們不需要改路徑,直接保持默認(rèn)路徑/usr/local,不然會出現(xiàn)各種報錯。如下圖

qt6 深度學(xué)習(xí)部署,qt,opencv,YOLO,深度學(xué)習(xí),c++,linux

?然后繼續(xù)configure和generate之后,沒有紅色提示說明配置成功。如果出現(xiàn)了紅色問題,那就搜一搜報錯,應(yīng)該都能搜到解決方法。

? ? ? ? 下面就是進(jìn)入到build文件夾目錄下,開始執(zhí)行命令

sudo make -j4
sudo make install

? ? ? ? 開始了漫長的編譯之路,希望每位讀者都能一次到100%,如果沒到,那就開始和作者一樣的痛苦改錯日記吧。

????????4)安裝后配置環(huán)境變量

? ? ? ? 在完成了編譯之后,需要配置opencv的環(huán)境變量,進(jìn)入目錄

cd /etc/ld.so.conf.d/
sudo vim opencv.conf

創(chuàng)建文件后插入

/usr/local

保存并退出,執(zhí)行:

sudo ldconfig

下面就是配置bash,

sudo vim /etc/bash.bashrc

在末尾添加:

PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/pkgconfig

export PKG_CONFIG_PATH

保存退出:執(zhí)行

source /etc/bash.bashrc

最后就是安裝mlocate

sudo apt-get update
sudo apt-get install mlocate

執(zhí)行更新資料庫:

sudo updatedb

最后就可以找一個opencv的qt程序測試一下,能不能打開一張圖片之類的。opencv的部署就至此結(jié)束啦

五、開發(fā)qt界面實現(xiàn)推理

? ?這部分沒有什么需要細(xì)講的,直接上代碼:

?(1)main.cpp
#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為主窗體運(yùn)行,其他沒有任何額外的功能

(2)頭文件

qt6 深度學(xué)習(xí)部署,qt,opencv,YOLO,深度學(xué)習(xí),c++,linux

頭文件有如上五個,其中mainwidget是主窗體的頭文件,MVCamera.h是??迪鄼C(jī)相關(guān)的,mythread.h是創(chuàng)建一個獨(dú)立的線程,以此來控制相機(jī)傳過來的圖像間隔,如果單純檢測視頻的話,可以不用這個。widget.h也是??倒I(yè)相機(jī)的相關(guān)頭文件,yolov5.h是有關(guān)推理的,著重講一下這個,其他的我相信大家都能看懂,我直接附代碼

? ?1)mainwidget.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);
    //存儲相機(jī)配置界面的指針
    Widget *wid=NULL;

    CMvCamera *m_pcMyMainCamera[MAX_MAINDEVICE_NUM]; // 相機(jī)指針對象

    cv::Mat *myImage_Main = new cv::Mat(); //保存相機(jī)圖像的圖像指針對象

    MyThread *myThread_Camera_Mainshow = NULL;      //相機(jī)畫面實時顯示線程對象

    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:
    // 狀態(tài)
    bool m_bOpenDevice;                  // 是否打開設(shè)備
    bool m_bStartGrabbing;               // 是否開始抓圖
    int m_nTriggerMode;                  // 觸發(fā)模式
    int m_bContinueStarted;
    int num;
    // 開啟過連續(xù)采集圖像
    MV_SAVE_IAMGE_TYPE m_nSaveImageType; // 保存圖像格式

    YoloV5 yolov5;

    Net net;
private slots:
    void on_pbn_start_grab_clicked();

    void closeW();               //關(guān)閉子窗體的槽函數(shù)

    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
2)MvCamera.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:枚舉設(shè)備 | en:Enumerate Device
    static int EnumDevices(unsigned int nTLayerType,
                           MV_CC_DEVICE_INFO_LIST *pstDevList);

    // ch:判斷設(shè)備是否可達(dá) | en:Is the device accessible
    static bool IsDeviceAccessible(MV_CC_DEVICE_INFO *pstDevInfo,
                                   unsigned int nAccessMode);

    // ch:打開設(shè)備 | en:Open Device
    int Open(MV_CC_DEVICE_INFO *pstDeviceInfo);

    // ch:關(guān)閉設(shè)備 | en:Close Device
    int Close();

    // ch:判斷相機(jī)是否處于連接狀態(tài) | en:Is The Device Connected
    bool IsDeviceConnected();

    // ch:注冊圖像數(shù)據(jù)回調(diào) | 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:主動獲取一幀圖像數(shù)據(jù) | 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:主動獲取一幀圖像數(shù)據(jù) | 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:設(shè)置SDK內(nèi)部圖像緩存節(jié)點(diǎn)個數(shù) | en:Set the number of the internal image
    // cache nodes in SDK
    int SetImageNodeNum(unsigned int nNum);

    // ch:獲取設(shè)備信息 | en:Get device information
    int GetDeviceInfo(MV_CC_DEVICE_INFO *pstDevInfo);

    // ch:獲取GEV相機(jī)的統(tǒng)計信息 | en:Get detect info of GEV camera
    int GetGevAllMatchInfo(MV_MATCH_INFO_NET_DETECT *pMatchInfoNetDetect);

    // ch:獲取U3V相機(jī)的統(tǒng)計信息 | en:Get detect info of U3V camera
    int GetU3VAllMatchInfo(MV_MATCH_INFO_USB_DETECT *pMatchInfoUSBDetect);

    // ch:獲取和設(shè)置Int型參數(shù),如 Width和Height,詳細(xì)內(nèi)容參考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:獲取和設(shè)置Enum型參數(shù),如 PixelFormat,詳細(xì)內(nèi)容參考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:獲取和設(shè)置Float型參數(shù),如
    // ExposureTime和Gain,詳細(xì)內(nèi)容參考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:獲取和設(shè)置Bool型參數(shù),如 ReverseX,詳細(xì)內(nèi)容參考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:獲取和設(shè)置String型參數(shù),如 DeviceUserID,詳細(xì)內(nèi)容參考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:執(zhí)行一次Command型命令,如 UserSetSave,詳細(xì)內(nèi)容參考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:探測網(wǎng)絡(luò)最佳包大小(只對GigE相機(jī)有效) | en:Detection network optimal
    // package size(It only works for the GigE camera)
    int GetOptimalPacketSize(unsigned int *pOptimalPacketSize);

    // ch:注冊消息異?;卣{(diào) | en:Register Message Exception CallBack
    int RegisterExceptionCallBack(
        void(__stdcall *cbException)(unsigned int nMsgType, void *pUser),
        void *pUser);

    // ch:注冊單個事件回調(diào) | en:Register Event CallBack
    int RegisterEventCallBack(
        const char *pEventName,
        void(__stdcall *cbEvent)(MV_EVENT_OUT_INFO *pEventInfo, void *pUser),
        void *pUser);

    // ch:強(qiáng)制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:設(shè)置網(wǎng)絡(luò)傳輸模式 | en:Set Net Transfer Mode
    int SetNetTransMode(unsigned int nType);

    // ch:像素格式轉(zhuǎn)換 | 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);

    //設(shè)置是否為觸發(fā)模式
    int setTriggerMode(unsigned int TriggerModeNum);

    //設(shè)置觸發(fā)源
    int setTriggerSource(unsigned int TriggerSourceNum);

    //軟觸發(fā)
    int softTrigger();

    //讀取buffer
    int ReadBuffer(cv::Mat &image);

    //讀取buffer
    int ReadBuffer2(cv::Mat &image,bool saveFlag,QByteArray imageName);

    //設(shè)置曝光時間
    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; // 用于從驅(qū)動獲取圖像的緩存
    unsigned int m_nBufSizeForDriver;
};

#endif // MVCAMERA_H
3)mythread.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);

        //發(fā)送獲取圖像處理的信號
        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
4)widget.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]; // 相機(jī)指針對象
    MV_CC_DEVICE_INFO_LIST m_stDevList;      // 存儲設(shè)備列表
    cv::Mat *myImage_L = new cv::Mat(); //保存左相機(jī)圖像的圖像指針對象
    cv::Mat *myImage_R = new cv::Mat(); //保存右相機(jī)有圖像的圖像指針對象
    int devices_num;                    // 設(shè)備數(shù)量

    MainWidget *mainWid = NULL;           //創(chuàng)建一個存儲主界面窗體的指針
public:
    MyThread *myThread_Camera_show = NULL; //相機(jī)實時顯示線程對象

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:
    // 狀態(tài)
    bool m_bOpenDevice;                  // 是否打開設(shè)備
    bool m_bStartGrabbing;               // 是否開始抓圖
    int m_nTriggerMode;                  // 觸發(fā)模式
    int m_bContinueStarted;              // 開啟過連續(xù)采集圖像
    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;     //重寫關(guān)閉事件處理函數(shù)
};
#endif // WIDGET_H

5)yolov5.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;             //結(jié)果類別id
    float confidence;   //結(jié)果置信度
    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; //網(wǎng)絡(luò)模型輸入大小
        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數(shù)組className,需要設(shè)置自己的類別數(shù),這里需要改一下,因為作者的類別數(shù)只有“ok”和“NG”,所有我將原有的數(shù)據(jù)集coco的80個類別給注釋掉了,自己根據(jù)需求更改相關(guān)參數(shù),都在頭文件里。

(3)cpp文件?
1)mainwidget.cpp
#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);                     //設(shè)置定時器觸發(fā)的間隔

    num=1;
    //將定時器與讀取數(shù)據(jù)流的函數(shù)連接起來,每當(dāng)定時器觸發(fā),執(zhí)行readFrame
    connect(timer,&QTimer::timeout,this,&MainWidget::readFrame);

    //將定時器與讀取相機(jī)幀率以及檢測的函數(shù)連接起來,每當(dāng)定時器觸發(fā),執(zhí)行yoloDetect

    //ui->startdetect->setEnabled(false);

    this->wid=new Widget();
    //點(diǎn)擊相機(jī)配置按鈕,顯示相機(jī)配置界面,隱藏主界面
    connect(ui->pbn_start_grab,&QPushButton::clicked,wid,[=]()
    {
        this->hide();
        wid->show();
    });

    //關(guān)閉相機(jī)配置界面后,顯示主界面
    connect(this->wid, &Widget::closedWid, this,[=]()
    {
        this->show();
    });

    //主界面接受信號后,會顯示主界面,隱藏相機(jī)界面
    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 *)));

    //設(shè)置打開圖片和攝像頭button為disable,只有當(dāng)加載模型后才會Enable
    ui->openfile->setEnabled(false);
    ui->pbn_start_grab->setEnabled(false);
}
MainWidget::~MainWidget()
{
    capture->release();
    delete capture;
    delete ui;
    delete wid;


}


//讀取流函數(shù)
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));
}


//根據(jù)定時器觸發(fā)實時檢測
void MainWidget::yoloDetect(Mat *myImage_Main)
{

    //讀取相機(jī)流
    //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++;
    }


}

//加載相機(jī)界面
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));
}

//關(guān)閉子窗體  顯示父窗體
void MainWidget::closeW()
{
    this->show();
}




//打開文件按鈕的槽函數(shù)
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);//顏色空間轉(zhuǎn)換
            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));

        //獲取整個幀數(shù)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));

        //設(shè)置開始幀()
        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()
{
    // 觸發(fā)模式標(biāo)記一下,切換觸發(fā)模式時先執(zhí)行停止采集圖像函數(shù)
    m_bContinueStarted = 1;

    if (m_nTriggerMode == TRIGGER_ON) {
        // 開始采集之后才創(chuàng)建workthread線程

            //開啟相機(jī)采集
            m_pcMyMainCamera[0]->StartGrabbing();
            int camera_Index=0;
            if (camera_Index == 0) {
                myThread_Camera_Mainshow->getCameraPtr(
                    m_pcMyMainCamera[0]); //線程獲取左相機(jī)指針
                myThread_Camera_Mainshow->getImagePtr(
                    myImage_Main); //線程獲取圖像指針
                myThread_Camera_Mainshow->getCameraIndex(0); //相機(jī) 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("您選擇了保存結(jié)果,保存路徑為/home/joe/program/VersionDetect/LiteTest/res_img");
    }
}
2)MvCamera.cpp
#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:枚舉設(shè)備 | en:Enumerate Device
int CMvCamera::EnumDevices(unsigned int nTLayerType,
                           MV_CC_DEVICE_INFO_LIST *pstDevList)
{
    return MV_CC_EnumDevices(nTLayerType, pstDevList);
}

// ch:判斷設(shè)備是否可達(dá) | en:Is the device accessible
bool CMvCamera::IsDeviceAccessible(MV_CC_DEVICE_INFO *pstDevInfo,
                                   unsigned int nAccessMode)
{
    return MV_CC_IsDeviceAccessible(pstDevInfo, nAccessMode);
}

// ch:打開設(shè)備 | 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:關(guān)閉設(shè)備 | 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:判斷相機(jī)是否處于連接狀態(tài) | en:Is The Device Connected
bool CMvCamera::IsDeviceConnected()
{
    return MV_CC_IsDeviceConnected(m_hDevHandle);
}

// ch:注冊圖像數(shù)據(jù)回調(diào) | 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:主動獲取一幀圖像數(shù)據(jù) | 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:主動獲取一幀圖像數(shù)據(jù) | 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:設(shè)置顯示窗口句柄 | en:Set Display Window Handle
int CMvCamera::DisplayOneFrame(MV_DISPLAY_FRAME_INFO *pDisplayInfo)
{
    return MV_CC_DisplayOneFrame(m_hDevHandle, pDisplayInfo);
}

// ch:設(shè)置SDK內(nèi)部圖像緩存節(jié)點(diǎn)個數(shù) | 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:獲取設(shè)備信息 | en:Get device information
int CMvCamera::GetDeviceInfo(MV_CC_DEVICE_INFO *pstDevInfo)
{
    return MV_CC_GetDeviceInfo(m_hDevHandle, pstDevInfo);
}

// ch:獲取GEV相機(jī)的統(tǒng)計信息 | 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相機(jī)的統(tǒng)計信息 | 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:獲取和設(shè)置Int型參數(shù),如 Width和Height,詳細(xì)內(nèi)容參考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:獲取和設(shè)置Enum型參數(shù),如 PixelFormat,詳細(xì)內(nèi)容參考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:獲取和設(shè)置Float型參數(shù),如 ExposureTime和Gain,詳細(xì)內(nèi)容參考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:獲取和設(shè)置Bool型參數(shù),如 ReverseX,詳細(xì)內(nèi)容參考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:獲取和設(shè)置String型參數(shù),如 DeviceUserID,詳細(xì)內(nèi)容參考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:執(zhí)行一次Command型命令,如 UserSetSave,詳細(xì)內(nèi)容參考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:探測網(wǎng)絡(luò)最佳包大小(只對GigE相機(jī)有效) | 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:注冊消息異?;卣{(diào) | 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:注冊單個事件回調(diào) | 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:強(qiáng)制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:設(shè)置網(wǎng)絡(luò)傳輸模式 | en:Set Net Transfer Mode
int CMvCamera::SetNetTransMode(unsigned int nType)
{
    return MV_GIGE_SetNetTransMode(m_hDevHandle, nType);
}

// ch:像素格式轉(zhuǎn)換 | 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);
//}

//設(shè)置是否為觸發(fā)模式
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;
    }
}

//設(shè)置觸發(fā)源
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;
    }
}

//發(fā)送軟觸發(fā)
int CMvCamera::softTrigger()
{
    int tempValue = MV_CC_SetCommandValue(m_hDevHandle, "TriggerSoftware");
    if (tempValue != 0) {
        return -1;
    } else {
        return 0;
    }
}

//讀取相機(jī)中的圖像
// 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 {
        //轉(zhuǎn)換圖像格式為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:輸入數(shù)據(jù)緩存 |
        // en:input data buffer
        stConvertParam.pSrcData =
            pDate; // ch:輸入數(shù)據(jù)緩存 | en:input data buffer
        stConvertParam.nSrcDataLen =
            stImageInfo.nFrameLen; // ch:輸入數(shù)據(jù)大小 | 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:輸出數(shù)據(jù)緩存 | 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;
}


//設(shè)置曝光時間
int CMvCamera::setExposureTime(float ExposureTimeNum)
{
    int tempValue =
        MV_CC_SetFloatValue(m_hDevHandle, "ExposureTime", ExposureTimeNum);
    if (tempValue != 0) {
        return -1;
    } else {
        return 0;
    }
}
3)mythread.cpp
#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); //發(fā)送信號lbl_camera_L接收并顯示

        emit GetPtr(imagePtr); //發(fā)送信號yolo進(jìn)行檢測并顯示


        msleep(30);
    }
}

4)widget.cpp
#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);

    // 相機(jī)初始化控件
    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);

    // 參數(shù)控件
    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; //相機(jī)線程對象


    //發(fā)送信號實現(xiàn)頁面切換
    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;
}

//創(chuàng)建關(guān)閉子窗體事件,顯示主窗體
void Widget::closeEvent(QCloseEvent *event)
{
    emit closedWid();     //發(fā)射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("暫無設(shè)備可連接,請檢查設(shè)備是否連接正確!");
        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);
    }
}

//打印相機(jī)的型號、ip等信息
QString Widget::PrintDeviceInfo(MV_CC_DEVICE_INFO *pstMVDevInfo, int num_index)
{
    QString cameraInfo_index;
    cameraInfo_index = QString::fromLocal8Bit("相機(jī)序號:");
    cameraInfo_index.append(QString::number(num_index+1));
    cameraInfo_index.append("\t\t");
    // ??礕IGE協(xié)議的相機(jī)
    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("相機(jī)型號:"));
        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("當(dāng)前相機(jī)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("相機(jī)型號:"));
        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("相機(jī)型號:未知"));
    }
    cameraInfo_index.append(QString::fromLocal8Bit("相機(jī)品牌:??低?));
    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);
    // 參數(shù)據(jù)控件
    ui->le_set_exposure->setEnabled(true);
    ui->le_set_gain->setEnabled(true);


    OpenDevices();
}

void Widget::OpenDevices()
{
    int nRet = MV_OK;
    // 創(chuàng)建相機(jī)指針對象
    for (unsigned int i = 0, j = 0; j < m_stDevList.nDeviceNum; j++, i++) {
        m_pcMyCamera[i] = new CMvCamera;
        // 相機(jī)對象初始化
        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]); //打開相機(jī)
        //設(shè)置觸發(fā)模式
        m_pcMyCamera[i]->setTriggerMode(TRIGGER_ON);
        //設(shè)置觸發(fā)源為軟觸發(fā)
        m_pcMyCamera[i]->setTriggerSource(TRIGGER_SOURCE);
        //設(shè)置曝光時間,初始為40000,并關(guān)閉自動曝光模式
        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()
{
    // 如果開始選擇的連續(xù)模式,切換到觸發(fā)模式之前,需要先停止采集
    if (m_bContinueStarted == 1) {
        on_pbn_stop_grabbing_clicked(); //先執(zhí)行停止采集
    }

    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()
{
    // 觸發(fā)模式標(biāo)記一下,切換觸發(fā)模式時先執(zhí)行停止采集圖像函數(shù)
    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) {
        // 開始采集之后才創(chuàng)建workthread線程
        for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++) {
            //開啟相機(jī)采集
            m_pcMyCamera[i]->StartGrabbing();
            camera_Index = i;
            if (camera_Index == 0) {
                myThread_Camera_show->getCameraPtr(
                    m_pcMyCamera[0]); //線程獲取左相機(jī)指針
                myThread_Camera_show->getImagePtr(
                    myImage_L); //線程獲取圖像指針
                myThread_Camera_show->getCameraIndex(0); //相機(jī) 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++) {
        //關(guān)閉相機(jī)
        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++) {
            //開啟相機(jī)采集
            m_pcMyCamera[i]->StartGrabbing();

            if (i == 0) {
                nRet = m_pcMyCamera[i]->CommandExecute("TriggerSoftware");
                m_pcMyCamera[i]->ReadBuffer(*myImage_L);
                display_myImage_L(myImage_L);       //左相機(jī)圖像
                display_myImage_Main(myImage_L);    //主界面顯示
            }
        }
    }
}

//在相機(jī)配置界面顯示
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)重載函數(shù),arg1 代表路徑文件名,
             * arg2 保存的類型,arg3 代表保存的質(zhì)量等級 */
            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++) {
        // 關(guān)閉線程、相機(jī)
        if (myThread_Camera_show->isRunning()) {
            myThread_Camera_show->requestInterruption();
            myThread_Camera_show->wait();
            m_pcMyCamera[0]->StopGrabbing();
        }

        m_pcMyCamera[i]->Close();
    }

    // 關(guān)閉之后再枚舉一遍
    memset(&m_stDevList, 0,
           sizeof(MV_CC_DEVICE_INFO_LIST)); // 初始化設(shè)備信息列表
    int devices_num = MV_OK;
    devices_num =
        CMvCamera::EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE,
                               &m_stDevList); // 枚舉子網(wǎng)內(nèi)所有設(shè)備,相機(jī)設(shè)備數(shù)量
}

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);
    // 參數(shù)控件
    ui->le_set_exposure->setEnabled(false);
    ui->le_set_gain->setEnabled(false);
    // 保存圖像控件
    ui->pbn_save_BMP->setEnabled(false);
    ui->pbn_save_JPG->setEnabled(false);

    // 關(guān)閉設(shè)備,銷毀線程
    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; // 一幀數(shù)據(jù)大小

            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圖片大?。簑idth * height * 3 + 2048(預(yù)留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);
            }
            // 設(shè)置對應(yīng)的相機(jī)參數(shù)
            MV_SAVE_IMAGE_PARAM_EX stParam = { 0 };
            stParam.enImageType = m_nSaveImageType; // 需要保存的圖像類型
            stParam.enPixelType = stImageInfo.enPixelType; // 相機(jī)對應(yīng)的像素格式
            stParam.nBufferSize =
                m_pcMyCamera[i]->m_nBufSizeForSaveImage; // 存儲節(jié)點(diǎn)的大小
            stParam.nWidth = stImageInfo.nWidth;         // 相機(jī)對應(yīng)的寬
            stParam.nHeight = stImageInfo.nHeight;       // 相機(jī)對應(yīng)的高
            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)
{
    //設(shè)置曝光時間
    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()
{
    //發(fā)送信號實現(xiàn)頁面切換
    //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);//如果訓(xùn)練集未對圖片進(jìn)行減去均值操作,則需要設(shè)置為這句
    //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;//結(jié)果id數(shù)組
    std::vector<float> confidences;//結(jié)果每個id對應(yīng)置信度數(shù)組
    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;  //輸出的網(wǎng)絡(luò)寬度是類別數(shù)+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長度數(shù)組變成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是顏色數(shù)組,對沒一個id隨機(jī)分配一種顏色
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;
}

這里需要講一下,如果如前面所示你用的單一輸出,如下圖

qt6 深度學(xué)習(xí)部署,qt,opencv,YOLO,深度學(xué)習(xí),c++,linux

要用?qt6 深度學(xué)習(xí)部署,qt,opencv,YOLO,深度學(xué)習(xí),c++,linux

outputLayerName來獲取數(shù)組,如作者的onnx模型,名稱為output,那就獲取整個output的權(quán)重,數(shù)據(jù),如果導(dǎo)出格式如下圖所示:

qt6 深度學(xué)習(xí)部署,qt,opencv,YOLO,深度學(xué)習(xí),c++,linux

那么你就要用

qt6 深度學(xué)習(xí)部署,qt,opencv,YOLO,深度學(xué)習(xí),c++,linux

以上的forword函數(shù)來獲取權(quán)重文件,其他地方基本無需改動,當(dāng)然肯定部署會出現(xiàn)各種報錯,在你讀懂了代碼之后,基本上都能改好

寫在最后:如果想要qt源碼文件,可以進(jìn)入以下鏈接,創(chuàng)作不易,謝謝大家支持

qt源碼文件文章來源地址http://www.zghlxwxcb.cn/news/detail-853689.html

到了這里,關(guān)于基于樹莓派Qt+opencv+yolov5-Lite+C++部署深度學(xué)習(xí)推理的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • C++模型部署:qt+yolov5/6+onnxruntime+opencv

    C++模型部署:qt+yolov5/6+onnxruntime+opencv

    作者平時主要是寫 c++ 庫的,界面方面了解不多,也沒有發(fā)現(xiàn)“美”的眼鏡,界面有點(diǎn)丑,大家多包涵。 本次介紹的項目主要是通過 cmake 構(gòu)建一個 基于 c++ 語言的,以 qt 為框架的,包含 opencv 第三方庫在內(nèi)的,跨平臺的,使用 ONNX RUNTIME 進(jìn)行前向推理的 yolov5/6 演示平臺。文章

    2024年02月05日
    瀏覽(23)
  • yolov5分割+檢測c++ qt 中部署,以opencv方式(詳細(xì)代碼(全)+復(fù)制可用)

    yolov5分割+檢測c++ qt 中部署,以opencv方式(詳細(xì)代碼(全)+復(fù)制可用)

    1:版本說明: qt 5.12.10 opencv 4.5.3 (yolov5模型部署要求opencv4.5.0) 2:檢測的代碼 yolo.h yolo.cpp 檢測的調(diào)用代碼測試案例 這段調(diào)用的例子,只要把frame 改成你們自己的圖片即可 4:分割的主要代碼 YoloSeg.h YoloSeg.cpp yolov5_seg_utils.h ?yolov5_seg_utils.cpp 分割的調(diào)用代碼測試案例 ?分割的

    2024年02月03日
    瀏覽(23)
  • 樹莓派部署YOLOv5模型

    本文章是關(guān)于樹莓派部署YOLOv5s模型,實際測試效果的FPS僅有0.15,不夠滿足實際檢測需要,各位大佬可以參考參考。 1、在樹莓派中安裝opencv(默認(rèn)安裝好python3) 2、導(dǎo)出onnx模型 從YOLOv5官網(wǎng)下載源代碼和YOLOv5s.pt文件 YOLOv5官網(wǎng) YOLOv5s.pt下載 按照作者提示安裝環(huán)境,使用它自帶

    2024年02月11日
    瀏覽(22)
  • 【問題記錄】樹莓派+OpenCV+YOLOv5目標(biāo)檢測(Pytorch框架)

    【問題記錄】樹莓派+OpenCV+YOLOv5目標(biāo)檢測(Pytorch框架)

    ?-【學(xué)習(xí)資料】 子豪兄的零基礎(chǔ)樹莓派教程 https://github.com/TommyZihao/ZihaoTutorialOfRaspberryPi/blob/master/%E7%AC%AC2%E8%AE%B2%EF%BC%9A%E6%A0%91%E8%8E%93%E6%B4%BE%E6%96%B0%E6%89%8B%E6%97%A0%E7%97%9B%E5%BC%80%E6%9C%BA%E6%8C%87%E5%8D%97.md#%E7%83%A7%E5%BD%95%E9%95%9C%E5%83%8F 第2講:樹莓派新手無痛開機(jī)指南【子豪兄的樹莓派

    2024年02月02日
    瀏覽(27)
  • 【解惑筆記】樹莓派+OpenCV+YOLOv5目標(biāo)檢測(Pytorch框架)

    【解惑筆記】樹莓派+OpenCV+YOLOv5目標(biāo)檢測(Pytorch框架)

    ?-【學(xué)習(xí)資料】 子豪兄的零基礎(chǔ)樹莓派教程 https://github.com/TommyZihao/ZihaoTutorialOfRaspberryPi/blob/master/%E7%AC%AC2%E8%AE%B2%EF%BC%9A%E6%A0%91%E8%8E%93%E6%B4%BE%E6%96%B0%E6%89%8B%E6%97%A0%E7%97%9B%E5%BC%80%E6%9C%BA%E6%8C%87%E5%8D%97.md#%E7%83%A7%E5%BD%95%E9%95%9C%E5%83%8F 第2講:樹莓派新手無痛開機(jī)指南【子豪兄的樹莓派

    2024年02月14日
    瀏覽(19)
  • QT+Opencv+yolov5實現(xiàn)監(jiān)測

    QT+Opencv+yolov5實現(xiàn)監(jiān)測

    功能說明:使用QT+Opencv+yolov5實現(xiàn)監(jiān)測 =============================== 倉庫鏈接:https://gitee.com/wangyoujie11/qt_yolov5.git git本倉庫到本地 一、環(huán)境配置 1.opencv配置 將OpenCV-MinGW-Build-OpenCV-4.5.2-x64文件夾放在自己的一個目錄下,如我的路徑: 編輯系統(tǒng)環(huán)境變量【配置完成之后,要 確定 】

    2024年04月11日
    瀏覽(23)
  • QT部署YOLOV5

    QT部署YOLOV5

    ??這篇文章主要用來記錄用pyqt5搭建YOLOV5的檢測平臺,代碼是在yoloV5官方代碼上加了個qt模塊,目前可以支持 GPU/CPU下pt/onnx推理 。 根據(jù)代碼中的requirements.txt進(jìn)行環(huán)境搭建,前提是你已有Python環(huán)境 這里需要注意的是,pyqt5需要配置下環(huán)境,參考連接為:安裝pyqt5,步驟如下:

    2024年02月05日
    瀏覽(19)
  • yolov5 opencv dnn部署 github代碼

    yolov5 opencv dnn部署 github代碼

    源碼地址 yolov5官網(wǎng)還提供的dnn、tensorrt推理鏈接 本人使用的opencv c++ github代碼,代碼作者非本人,也是上面作者推薦的鏈接之一 實現(xiàn)推理源碼中作者的yolov5s.onnx 推理條件 實現(xiàn)推理code中作者的yolov5s.onnx windows 10 Visual Studio 2019 Nvidia GeForce GTX 1070 opencv 4.5.5、opencv4.7.0 (注意 4.7.0代碼

    2024年01月23日
    瀏覽(49)
  • yolov5 opencv dnn部署自己的模型

    yolov5 opencv dnn部署自己的模型

    github開源代碼地址 yolov5官網(wǎng)還提供的dnn、tensorrt推理鏈接 本人使用的opencv c++ github代碼,代碼作者非本人,也是上面作者推薦的鏈接之一 如果想要嘗試直接運(yùn)行源碼中的yolo.cpp文件和yolov5s.pt推理sample.mp4,請參考這個鏈接的介紹 使用github源碼結(jié)合自己導(dǎo)出的onnx模型推理自己的

    2024年01月23日
    瀏覽(48)
  • YOLOv5 5.0版本 + OpenCV 4.5.2 部署

    YOLOv5 5.0版本 + OpenCV 4.5.2 部署

    提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔 版本一定要和我的一致,不然不保證能run起來?。?! 該任務(wù)我們選擇YOLOv5 5.0 版本。在https://github.com/ultralytics/yolov5中,可以選擇對應(yīng)的版本下載。由于GitHub上 v5 5.0 版本的C++代碼居多,故選擇 v5 5.0。(

    2024年02月10日
    瀏覽(15)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包