QT + C++ + 海康威视工业相机二次开发 2021-05-12

  • Post author:
  • Post category:其他

1.了解海康威视工业相机

本人学习参考的是:boss_dog的博客,里面有详细的分析相机的数据,各种相机的区别,在VS中部署SDK的环境变量以及官方例程.

1.1.下载SDK

海康威视的工业相机二次开发首先是需要在官方下载相机的SDK,下载地址_官方下载地址,根据自身的环境区下载需要的SDK,本人下载的是(机器视觉工业相机客户端MVS V3.3.1(Windows)).

下载后打开下图中的文件,是VS+C++的Demo,本人用到的是第一个demo,打开相机保存图片.

 

1.2.环境配置

PS:不管运行海康威视的哪个例程,都需要先配置下环境
在VS项目中配置opencv和mvs的动态链接库等(用到Opencv的话)
①在VS中配置Opencv
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
②在VS中配置MVS
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

环境配置完成后,将官方的demo导入到VS中基本上就能运行了.

下图就是实现基本功能的代码,在BasicDemoDlg.cpp中就是自己写的代码根据调用官方的SDK来实现基本功能.

2.在QT中实现官方demo中的功能

2.1.首先我们需要在qt中配置好实现功能的环境:

2.1.1 配置好相机SDK的环境,参考博客:大樱桃的博客_大_樱_桃_CSDN博客-Halcon,工业相机,Halcon_C#l联合编程领域博主.

先在QT中创建一个项目,将海康的MVS文件下Development文件里面的Includes以及Libraries文件复制到qt的项目文件下.

复制完成后在QT中右击项目文件,点击添加库,选择外部库,点击下一步,选择库文件,选择平台和静态链接,点下一步就行了.

             

导入库后生成的代码片段:

生成代码片段后再加入Include,相机的头文件,相机的SDK和环境就配置完成了.

INCLUDEPATH += $$PWD/Includes
DEPENDPATH += $$PWD/Includes

2.1.2 配置opencv的环境变量:在配置opencv的路上我也是经历了很多坎坷,,,查阅无数文档,大部分都是使用MinGV,可以参考博客:拜小白教你Qt5.8.0+OpenCV3.2.0配置教程(详细版)_拜小白的成长之路,告别小白-CSDN博客,但是我是先使用的VS的运行环境,然后QT在VS的运行环境下建立的,可以参考Qt5.9.6+opencv+VS2017的安装及配置_我内疚的博客-CSDN博客。反正这种配置环境的路上就是不断地查找文档,不断地更改。,慢慢摸索,,最终我在qt上配置的opencv的代码是:

INCLUDEPATH += D:\QtDemo\opencv\include
INCLUDEPATH += D:\QtDemo\opencv\include/opencv2
CONFIG(debug, debug|release): {
LIBS += -LD:\QtDemo\opencv/lib \
-lopencv_world440 \
-lopencv_world440d
} else:CONFIG(release, debug|release): {
LIBS += -LD:\QtDemo\opencv/lib \
-lopencv_world440 \
-lopencv_world440d
}

环境配置完成后,接着把相机封装好的函数体:cpp文件和头文件复制到项目文件下:MVCamera.cpp和MVCamera.h

接着又是参考:海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(二)_boss-dog的博客-CSDN博客其中的源代码,结合上官方自带的SDK,就完成了一些基本的显示相机采集的画面,保存图片,获取相机IP,软触发等功能。

3.我的源代码是:

MVCamera.h

/************************************************************************/
/* 以C++接口为基础,对常用函数进行二次封装,方便用户使用                */
/************************************************************************/
 
#ifndef _MV_CAMERA_H_
#define _MV_CAMERA_H_
 
#include "Includes/MvCameraControl.h"
#include <string.h>
 
#include"opencv2/opencv.hpp"
#include"opencv2/imgproc/types_c.h"
 
 
#ifndef MV_NULL
#define MV_NULL    0
#endif
 
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: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:Free image buffer
    int FreeImageBuffer(MV_FRAME_OUT* pFrame);
 
    // 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 unsigned int* pIntValue);
    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);
 
 
private:
 
    void*               m_hDevHandle;
 
public:
    unsigned int     m_nTLayerType;
 
    unsigned char* m_pBufForSaveImage;         // 用于保存图像的缓存
    unsigned int    m_nBufSizeForSaveImage;
 
    unsigned char* m_pBufForDriver;            // 用于从驱动获取图像的缓存
    unsigned int    m_nBufSizeForDriver;
 
};
 
#endif//_MV_CAMERA_H_
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>
 
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, int index);
 
private:
    CMvCamera* cameraPtr = NULL;
    cv::Mat* imagePtr = NULL;
    int cameraIndex = NULL;
    int TriggerMode;
};
 
#endif // MYTHREAD_H
#pragma once

widget.h

#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include <Windows.h>
#include "MvCamera.h"
#include "Includes/CameraParams.h"
#include "minwindef.h"
#include "stringapiset.h"
#include "tchar.h"
#include "mythread.h"
#include "QString"
#include "QMessageBox"
#include <windows.h>
#include "WinUser.h"
 
//声明相机最大数量
#define MAX_DEVICE_NUM    2
 
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
 
class Widget : public QWidget
{
    Q_OBJECT
 
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
 
//按钮函数
private slots:
    void display_myImage(const Mat* imagePrt, int cameraIndex);
    void on_checkedbtn_clicked();
    void on_openbtn_clicked();
 
 
    void on_closebtn_clicked();
 
    void on_rbnt_Continue_Mode_clicked();
 
    void on_bntStartGrabbing_clicked();
 
    void on_rbnt_SoftTigger_Mode_clicked();
 
    void on_bntStopGrabbing_clicked();
 
    void on_bntSoftwareOnce_clicked();
 
 
 
//自定义对象
    void on_bntSave_BMP_clicked();
 
    void on_bntSave_JPG_clicked();
 
public:
    CMvCamera* m_pcMyCamera[MAX_DEVICE_NUM];         // 相机指针对象
    MV_CC_DEVICE_INFO_LIST m_stDevList;              // 设备信息列表结构体变量,用来存储设备列表
    _MV_CC_DEVICE_INFO_ m_SpecialInfo;               //设备信息
    int devices_num;//设备数量
    int nRet;
    MyThread* myThread_Camera;//相机线程
    void* m_hGrabThread;                        // ch:取流线程句柄 | en:Grab thread handle
    BOOL m_bThreadState;
    BOOL m_bOpenDevice;                        // ch:是否打开设备 | en:Whether to open device
    BOOL m_bStartGrabbing;                     // ch:是否开始抓图 | en:Whether to start grabbing
 
    int m_nTriggerMode;                        //触发模式
    int m_bContinueStarted;                   // 开启过连续采集图像
    cv::Mat* myImage = new cv::Mat();              //用于保存相机图像的图像指针对象
     MV_SAVE_IAMGE_TYPE   m_nSaveImageType;      // ch:保存图像格式 | en:Save Image Type
 
//自定义方法
private:
    void OpenDevices();                    // ch:打开设备 | en:Open device
    void CloseDevices();                   // ch:关闭设备 | en:Close Device
 
    //错误信息
    void ShowErrorMsg(QString qMessage, int nErrorNum);
 
    //保存图片
    int SaveImage(MV_SAVE_IAMGE_TYPE m_nSaveImageType);
 
 
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

MVCamera.cpp

#include "MvCamera.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: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:Free image buffer
int CMvCamera::FreeImageBuffer(MV_FRAME_OUT* pFrame)
{
    return MV_CC_FreeImageBuffer(m_hDevHandle, pFrame);
}
 
// 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 MVCC_INTVALUE_EX *pIntValue)
//{
//    return MV_CC_GetIntValueEx(m_hDevHandle, strKey, pIntValue);
//}
 
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 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;   //ch:输出像素格式 | 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;
}

mytheard.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::get_TriggerMode(int m_nTriggerMode)
//{
//	TriggerMode = m_nTriggerMode;
//}
 
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;
        /*emit mess();*/
        emit Display(imagePtr, cameraIndex);//发送信号 img_display_label接收并显示
        msleep(30);
    }
}

widget.cpp

#include <QWidget>
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include "MvCamera.h"
#include "QFileDialog"
 
#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
 
 
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //初始化
    ui->checkedbtn->setEnabled(true);
    ui->openbtn->setEnabled(false);
    ui->closebtn->setEnabled(false);
    ui->rbnt_Continue_Mode->setEnabled(false);
    ui->rbnt_SoftTigger_Mode->setEnabled(false);
    ui->bntStartGrabbing->setEnabled(false);
    ui->bntStopGrabbing->setEnabled(false);
    ui->bntSoftwareOnce->setEnabled(false);
    ui->bntSave_BMP->setEnabled(false);
    ui->bntSave_JPG->setEnabled(false);
 
    m_bThreadState =false;
    m_bStartGrabbing = FALSE;
    m_bOpenDevice = FALSE;
    devices_num = 0;
    nRet = MV_OK;
    m_hGrabThread = NULL;
    m_bContinueStarted = 0;
    m_nSaveImageType = MV_Image_Bmp;
 
    //实例化
    myThread_Camera = new MyThread();
    connect(myThread_Camera,SIGNAL(Display(const Mat*,int)),this,SLOT(display_myImage(const Mat*,int)));
    connect(myThread_Camera,SIGNAL(mess()),this,SLOT(display_myImage(const Mat*,int)));
 
}
 
Widget::~Widget()
{
    delete ui;
}
 
//错误信息
// ch:显示错误信息 | en:Show error message
void Widget::ShowErrorMsg(QString qMessage, int nErrorNum)
{
    QString errorMsg;
    if (nErrorNum == 0)
    {
        errorMsg= qMessage;
    }
    else
    {
        errorMsg=QString("%1: Error = %2: ").arg(qMessage).arg(nErrorNum);
    }
 
    switch(nErrorNum)
    {
    case 1:           errorMsg += "Error or invalid handle ";                                         break;
    case 2:          errorMsg += "Not supported function ";                                          break;
    case 3:          errorMsg += "Cache is full ";                                                   break;
    case 4:        errorMsg += "Function calling order error ";                                    break;
    case 5:        errorMsg += "Incorrect parameter ";                                             break;
    case 6:         errorMsg += "Applying resource failed ";                                        break;
    case 7:           errorMsg += "No data ";                                                         break;
    case 8:     errorMsg += "Precondition error, or running environment changed ";              break;
    case 9:          errorMsg += "Version mismatches ";                                              break;
    case 10:     errorMsg += "Insufficient memory ";                                             break;
    case 11:   errorMsg += "Abnormal image, maybe incomplete image because of lost packet ";   break;
    case 12:           errorMsg += "Unknown error ";                                                   break;
    case 13:       errorMsg += "General error ";                                                   break;
    case 14:        errorMsg += "Node accessing condition error ";                                  break;
    case 15:	errorMsg += "No permission ";                                                   break;
    case 16:             errorMsg += "Device is busy, or network disconnected ";                         break;
    case 17:            errorMsg += "Network error ";                                                   break;
    }
 
    QMessageBox::information(NULL, "PROMPT", errorMsg , QMessageBox::Yes || QMessageBox::No , QMessageBox::Yes);
}
 
//查找设备
void Widget::on_checkedbtn_clicked()
{
 
    QString str;
    memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));    // ch:初始化设备信息列表
    nRet = CMvCamera::EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &m_stDevList);// ch:枚举子网内所有设备,相机设备数量
    devices_num = m_stDevList.nDeviceNum;
    if (devices_num > 0)
    {
        ui->openbtn->setEnabled(true);
       // 设备数大于0,打印第一台设备信息
//        qDebug() << m_stDevList.pDeviceInfo[0];
//        qDebug() << m_stDevList.nDeviceNum;
//        qDebug() << m_SpecialInfo.SpecialInfo.stGigEInfo.chModelName;
//        qDebug() <<m_SpecialInfo.SpecialInfo.stGigEInfo.chManufacturerName;
         wchar_t* pUserName = NULL;
        int nIp1 = ((m_stDevList.pDeviceInfo[0]->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24);//将相机的ip地址转成十进制
        int nIp2 = ((m_stDevList.pDeviceInfo[0]->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16);
        int nIp3 = ((m_stDevList.pDeviceInfo[0]->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8);
        int nIp4 = (m_stDevList.pDeviceInfo[0]->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff);
 
        if (strcmp("", (LPCSTR)(m_SpecialInfo.SpecialInfo.stGigEInfo.chUserDefinedName)) != 0)//空字符串与用户自定义名称比较,如果用户有自定义名字那么就用用户自定义名字,如果没有就用厂商名称
        {
            DWORD dwLenUserName = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)(m_SpecialInfo.SpecialInfo.stGigEInfo.chUserDefinedName), -1, NULL, 0);
            pUserName = new wchar_t[dwLenUserName];
            MultiByteToWideChar(CP_ACP, 0, (LPCSTR)(m_SpecialInfo.SpecialInfo.stGigEInfo.chUserDefinedName), -1, pUserName, dwLenUserName);
        }
        else
        {
            char strUserName[256] = {0};
            sprintf_s(strUserName, 256, "%s %s (%s)", m_SpecialInfo.SpecialInfo.stGigEInfo.chManufacturerName,
                m_SpecialInfo.SpecialInfo.stGigEInfo.chModelName,
                m_SpecialInfo.SpecialInfo.stGigEInfo.chSerialNumber);
            DWORD dwLenUserName = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)(strUserName), -1, NULL, 0);
            pUserName = new wchar_t[dwLenUserName];
            MultiByteToWideChar(CP_ACP, 0, (LPCSTR)(strUserName), -1, pUserName, dwLenUserName);
        }
        str = QString("相机个数:[%1],相机IP:(%3.%4.%5.%6 )").arg(m_stDevList.nDeviceNum).arg(nIp1).arg(nIp2).arg(nIp3).arg(nIp4);
        ui->textEdit->setText(str);
        qDebug() << str;
        qDebug() << m_pcMyCamera;
    }else{
       ShowErrorMsg(("NO DEVICE !!!"), 0);
    }
}
 
 
void Widget::OpenDevices(){
    m_bThreadState = true;
    m_bOpenDevice = true;
    // 创建相机指针对象
    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]); //打开相机
//        if(nRet != MV_OK){
//            ShowErrorMsg(("Open Fill"),1);
//        }
 
        //设置触发模式
        m_pcMyCamera[i]->setTriggerMode(TRIGGER_ON);
        //设置触发源为软触发
        m_pcMyCamera[i]->setTriggerSource(TRIGGER_SOURCE);
        qDebug() << m_pcMyCamera[i];
    }
}
 
//打开设备
void Widget::on_openbtn_clicked()
{
    OpenDevices();
    if(nRet !=MV_OK){
        ShowErrorMsg(("Open Fill"),1);
    }else{
        ui->openbtn->setEnabled(false);
        ui->closebtn->setEnabled(true);
        ui->rbnt_Continue_Mode->setEnabled(true);
        ui->rbnt_SoftTigger_Mode->setEnabled(true);
        ui->bntStartGrabbing->setEnabled(true);
    }
 
}
 
//关闭设备
void Widget::CloseDevices()
{
    for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++)
    {
       m_bThreadState = FALSE;
       myThread_Camera->requestInterruption();
       myThread_Camera->wait();
       m_pcMyCamera[i]->StopGrabbing();
       m_pcMyCamera[i]->Close();
       m_bStartGrabbing = FALSE;
       m_bOpenDevice = FALSE;
    }
}
 
// ch:按下关闭设备按钮:关闭设备 ,包含销毁句柄
void Widget::on_closebtn_clicked()
{
    ui->openbtn->setEnabled(true);
    ui->closebtn->setEnabled(false);
    ui->bntSoftwareOnce->setEnabled(false);
    ui->bntStartGrabbing->setEnabled(false);
    ui->bntStopGrabbing->setEnabled(false);
    ui->rbnt_Continue_Mode->setEnabled(false);
    ui->rbnt_SoftTigger_Mode->setEnabled(false);
 
    //销毁句柄
    CloseDevices();
    qDebug() << m_pcMyCamera;
}
 
//按下连续采集按钮
void Widget::on_rbnt_Continue_Mode_clicked()
{
    ui->bntStartGrabbing->setEnabled(true);
 
    m_nTriggerMode = TRIGGER_ON;
}
 
// ch:按下触发模式按钮 | en:Click Trigger Mode button
void Widget::on_rbnt_SoftTigger_Mode_clicked()
{
    if (m_bContinueStarted == 1) // 从连续采集模式已经正在采集的状态切换过来
    {
        on_bntStopGrabbing_clicked();//先执行停止采集
    }
    m_bContinueStarted = 0;
    m_nTriggerMode = TRIGGER_OFF;
    for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++)
    {
        m_pcMyCamera[i]->setTriggerMode(m_nTriggerMode);
    }
    ui->bntStartGrabbing->setEnabled(false);
    ui->bntStopGrabbing->setEnabled(true);
    ui->bntSoftwareOnce->setEnabled(true);
}
 
//软触发一次
void Widget::on_bntSoftwareOnce_clicked()
{
    ui->bntSave_BMP->setEnabled(true);
    ui->bntSave_JPG->setEnabled(true);
 
    if (m_nTriggerMode == TRIGGER_OFF)
    {
        nRet = MV_OK;
        for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++)
        {
            //开启相机采集
            m_pcMyCamera[i]->StartGrabbing();
                nRet = m_pcMyCamera[i]->CommandExecute("TriggerSoftware");
                m_pcMyCamera[i]->ReadBuffer(*myImage);
                display_myImage(myImage, i);//相机图像
        }
 
    }
}
 
 
// 开始采集图像
void Widget::on_bntStartGrabbing_clicked()
{
 
    if(m_bContinueStarted == 0){
        on_bntStopGrabbing_clicked();
    }
    m_bContinueStarted = 1; // 为触发模式标记一下,切换触发模式时先执行停止采集图像函数
 
    // 图像采集控件
    ui->bntStartGrabbing->setEnabled(false);
    ui->bntStopGrabbing->setEnabled(true);
    ui->bntSoftwareOnce->setEnabled(false);
    // 保存图像控件
    ui->bntSave_BMP->setEnabled(true);
    ui->bntSave_JPG->setEnabled(true);
 
    // 先判断什么模式,再判断是否正在采集
    if (m_nTriggerMode == TRIGGER_ON)
    {
        // ch:开始采集之后才创建workthread线程 | en:Create workthread after start grabbing
        for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++)
        {
            //开启相机采集
            m_pcMyCamera[i]->StartGrabbing();
            myThread_Camera->getCameraPtr(m_pcMyCamera[i]);//线程获取相机指针
            myThread_Camera->getImagePtr(myImage);//线程获取图像指针
            myThread_Camera->getCameraIndex(i); //相机数
            if(!myThread_Camera->isRunning()){
                myThread_Camera->start();
                m_pcMyCamera[i]->softTrigger();
                m_pcMyCamera[i]->ReadBuffer(*myImage);
 
                //ui->Display_Camera_Image->setPixmap(m_pcMyCamera[i]->ReadBuffer(*myImage));
            }
        }
    }
}
 
 
//停止采集
void Widget::on_bntStopGrabbing_clicked()
{
    ui->bntStartGrabbing->setEnabled(true);
    ui->bntStopGrabbing->setEnabled(false);
    ui->bntSave_BMP->setEnabled(false);
    ui->bntSave_JPG->setEnabled(false);
    ui->bntSoftwareOnce->setEnabled(false);
    for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++)
    {
        //停止线程,相机停止采集
        if (myThread_Camera->isRunning())
        {
            m_pcMyCamera[i]->StopGrabbing();
            myThread_Camera->requestInterruption();
            myThread_Camera->wait();
        }
    }
}
 
 
//显示图像
void Widget::display_myImage(const Mat* imagePrt, int cameraIndex)
{
    cv::Mat rgb;
    cv::cvtColor(*imagePrt, rgb, CV_BGR2RGB);
 
    //判断是黑白、彩色图像
    QImage QmyImage;
    if (rgb.channels() > 1)
    {
//        QmyImage = QImage((const unsigned char*)(rgb.data), rgb.cols, rgb.rows, QImage::Format_RGB888);
 
        QmyImage =QImage((const unsigned char*)(rgb.data),
                            rgb.cols,rgb.rows,
                            rgb.cols*rgb.channels(),
                            QImage::Format_RGB888);
 
//        cv::namedWindow("test",cv::WINDOW_FREERATIO);
//        cv::imshow("test",rgb);
//        cv::waitKey(0);
    }
    else
    {
        QmyImage = QImage((const unsigned char*)(rgb.data), rgb.cols, rgb.rows, QImage::Format_Indexed8);
    }
 
    QmyImage = (QmyImage).scaled(ui->Display_Camera_Image->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    //显示图像
    ui->Display_Camera_Image->setPixmap(QPixmap::fromImage(QmyImage));
    ui->Display_Camera_Image->show();
//    Sleep(1);
}
 
 
 
 
//保存图片
int Widget::SaveImage(MV_SAVE_IAMGE_TYPE m_nSaveImageType){
    // ch:获取1张图 | en:Get one frame
    MV_FRAME_OUT_INFO_EX stImageInfo = { 0 };
    memset(&stImageInfo, 0, sizeof(MV_FRAME_OUT_INFO_EX));
    unsigned int nDataLen = 0;
    nRet = MV_OK;
    for (int i = 0; i < devices_num; i++)
    {
        // ch:仅在第一次保存图像时申请缓存,在 CloseDevice 时释放
        // en:Request buffer first time save image, release after CloseDevice
        if (NULL == m_pcMyCamera[i]->m_pBufForDriver)
        {
            unsigned int nRecvBufSize = 0;
            nRet = 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)
        {
            // ch:仅在第一次保存图像时申请缓存,在 CloseDevice 时释放
            // en:Request buffer first time save image, release after CloseDevice
            if (NULL == m_pcMyCamera[i]->m_pBufForSaveImage)
            {
                // ch:BMP图片大小:width * height * 3 + 2048(预留BMP头大小)
                // en:BMP image size: width * height * 3 + 2048 (Reserved BMP header size)
                m_pcMyCamera[i]->m_nBufSizeForSaveImage = stImageInfo.nWidth * stImageInfo.nHeight * 3 + 2048;
 
                m_pcMyCamera[i]->m_pBufForSaveImage = (unsigned char*)malloc(m_pcMyCamera[i]->m_nBufSizeForSaveImage);
 
            }
            // ch:设置对应的相机参数 | en:Set camera parameter
            MV_SAVE_IMAGE_PARAM_EX stParam = { 0 };
            stParam.enImageType = m_nSaveImageType; // ch:需要保存的图像类型 | en:Image format to save;
            stParam.enPixelType = stImageInfo.enPixelType;  // 相机对应的像素格式 | en:Pixel format
            stParam.nBufferSize = m_pcMyCamera[i]->m_nBufSizeForSaveImage;  // 存储节点的大小 | en:Buffer node size
            stParam.nWidth = stImageInfo.nWidth;         // 相机对应的宽 | en:Width
            stParam.nHeight = stImageInfo.nHeight;          // 相机对应的高 | en:Height
            stParam.nDataLen = stImageInfo.nFrameLen;
            stParam.pData = m_pcMyCamera[i]->m_pBufForDriver;
            stParam.pImageBuffer = m_pcMyCamera[i]->m_pBufForSaveImage;
            stParam.nJpgQuality = 90;       // ch:jpg编码,仅在保存Jpg图像时有效。保存BMP时SDK内忽略该参数
 
            nRet = m_pcMyCamera[i]->SaveImage(&stParam);
 
            char chImageName[IMAGE_NAME_LEN] = { 0 };
            if (MV_Image_Bmp == stParam.enImageType)
            {//图片输出格式为BMP
                /*sprintf_s(chImageName, IMAGE_NAME_LEN, "Image_w%d_h%d_fn%03d_L.bmp", stImageInfo.nWidth, stImageInfo.nHeight, stImageInfo.nFrameNum);*/
                //sprintf_s(chImageName, IMAGE_NAME_LEN, "%03d_L.bmp", stImageInfo.nFrameNum);
                sprintf_s(chImageName, IMAGE_NAME_LEN, "%d-current_image.bmp", stImageInfo.nFrameNum);
            }
            else if (MV_Image_Jpeg == stParam.enImageType)
            {
                //sprintf_s(chImageName, IMAGE_NAME_LEN, "Image_w%d_h%d_fn%03d_L.bmp", stImageInfo.nWidth, stImageInfo.nHeight, stImageInfo.nFrameNum);
                sprintf_s(chImageName, IMAGE_NAME_LEN, "%d-current_image.jpg", stImageInfo.nFrameNum);
            }
            //qDebug() << chImageName;
            //将图片保存到指定路径
            QString filename=QFileDialog::getSaveFileName(this,tr("save Image"),chImageName);
            QByteArray ba = filename.toLatin1();
            char* Filename = ba.data(); //将QString装换为char*
            FILE* fp = fopen(Filename, "wb");//只写打开或新建一个二进制文件;只允许写数据
 
            fwrite(m_pcMyCamera[i]->m_pBufForSaveImage, 1, stParam.nImageLen, fp);
            //ui->label_debug->setText("save imgs");
            fclose(fp);
        }
    }
    return MV_OK;
}
 
//图片保存为BMP
void Widget::on_bntSave_BMP_clicked()
{
    nRet = SaveImage(MV_Image_Bmp);
    if(nRet != MV_OK){
        ShowErrorMsg("NO IMAGE",11);
    }else{
        QMessageBox::information(NULL,"SAVE BMP","Save Image Successed",QMessageBox::Yes);
    }
}
 
//图片保存为JPG
void Widget::on_bntSave_JPG_clicked()
{
    nRet = SaveImage(MV_Image_Jpeg);
    if(nRet != MV_OK){
        ShowErrorMsg("NO IMAGE",11);
    }else{
        QMessageBox::information(NULL,"SAVE JPEG","Save Image Successed",QMessageBox::Yes);
    }
}

4.下面是实现的效果图:


版权声明:本文为weixin_45739324原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。