相关文章推荐

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天, 点击查看活动详情

近期在Qt环境下进行海康工业相机的使用开发,发现海康提供的示例没有Qt的demo,而其中有基于MFC框架的示例,所以在这里基于该示例进行了Qt调用HIK工业相机的SDK开发,并将相关代码展现出来以便大家学习,如有错误之处,欢迎大家批评指正。

提示:以下是本篇文章正文内容,下面案例可供参考

一、环境配置

我的项目示例所用环境是QT5.14+OpenCV_4.5.1,至于如何配置OpenCv环境,具体的可以查看我之前写的这篇文章: Window下Qt5.14_MinGW_64bit+CMake_3.24+OpenCV_4.5.1环境搭建

二、项目准备

这里我是已经分类好了,将OpenCV及SDK文件夹放置程序同级目录,里面包含需要的一些头文件,库文件等等,下面pro文件中添加的代码可视具体情况而定:

然后在MyCamera.pro文件中添加下列代码:

#OpenCV
INCLUDEPATH += $$PWD/OpenCV/Includes
LIBS += -L $$PWD/OpenCV/Lib/libopencv_*.a
INCLUDEPATH += $$PWD/SDK/Includes
DEPENDPATH += $$PWD/SDK/Includes
LIBS += -L $$PWD/SDK/Lib/MvCameraControl.lib

三、示例完整代码展示/下载链接

1.cmvcamera.h(直接从海康提供的SDK中复制)

/************************************************************************/
/* 以C++接口为基础,对常用函数进行二次封装,方便用户使用                */
/************************************************************************/
#ifndef _MV_CAMERA_H_
#define _MV_CAMERA_H_
#include "MvCameraControl.h"
#include <string.h>
#include "opencv2/opencv.hpp"
//注意此处可能会跟系统函数定义冲突
using namespace cv;
#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: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 MVCC_INTVALUE_EX *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);
    int GetEnumEntrySymbolic(IN const char* strKey, IN MVCC_ENUMENTRY* pstEnumEntry);
    // 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);
    // ch:绘制圆形辅助线 | en:Draw circle auxiliary line
    int DrawCircle(MVCC_CIRCLE_INFO* pCircleInfo);
    // ch:绘制线形辅助线 | en:Draw lines auxiliary line
    int DrawLines(MVCC_LINES_INFO* pLinesInfo);
    //读取buffer
    int ReadBuffer(Mat &image);
private:
    void *m_hDevHandle;
    //用于保存图像的缓存
    unsigned int m_nBufSizeForSaveImage;
#endif//_MV_CAMERA_H_

2.cmvcamera.cpp

#include "cmvcamera.h"
CMvCamera::CMvCamera()
    m_hDevHandle = MV_NULL;
CMvCamera::~CMvCamera()
    if (m_hDevHandle)
        MV_CC_DestroyHandle(m_hDevHandle);
        m_hDevHandle = MV_NULL;
// ch:获取SDK版本号 | en:Get SDK Version
int CMvCamera::GetSDKVersion()
    return MV_CC_GetSDKVersion();
// ch:枚举设备 | en:Enumerate Device
int CMvCamera::EnumDevices(unsigned int nTLayerType, MV_CC_DEVICE_INFO_LIST* pstDevList)
    return MV_CC_EnumDevices(nTLayerType, pstDevList);
// ch:判断设备是否可达 | en:Is the device accessible
bool CMvCamera::IsDeviceAccessible(MV_CC_DEVICE_INFO* pstDevInfo, unsigned int nAccessMode)
    return MV_CC_IsDeviceAccessible(pstDevInfo, nAccessMode);
// ch:打开设备 | en:Open Device
int CMvCamera::Open(MV_CC_DEVICE_INFO* pstDeviceInfo)
    if (MV_NULL == pstDeviceInfo)
        return MV_E_PARAMETER;
    if (m_hDevHandle)
        return MV_E_CALLORDER;
    int nRet  = MV_CC_CreateHandle(&m_hDevHandle, pstDeviceInfo);
    if (MV_OK != nRet)
        return nRet;
    nRet = MV_CC_OpenDevice(m_hDevHandle);
    if (MV_OK != nRet)
        MV_CC_DestroyHandle(m_hDevHandle);
        m_hDevHandle = MV_NULL;
    return nRet;
// ch:关闭设备 | en:Close Device
int CMvCamera::Close()
    if (MV_NULL == m_hDevHandle)
        return MV_E_HANDLE;
    MV_CC_CloseDevice(m_hDevHandle);
    int nRet = MV_CC_DestroyHandle(m_hDevHandle);
    m_hDevHandle = MV_NULL;
    return nRet;
// ch:判断相机是否处于连接状态 | en:Is The Device Connected
bool CMvCamera::IsDeviceConnected()
    return MV_CC_IsDeviceConnected(m_hDevHandle);
// ch:注册图像数据回调 | en:Register Image Data CallBack
int CMvCamera::RegisterImageCallBack(void(__stdcall* cbOutput)(unsigned char * pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser), void* pUser)
    return MV_CC_RegisterImageCallBackEx(m_hDevHandle, cbOutput, pUser);
// ch:开启抓图 | en:Start Grabbing
int CMvCamera::StartGrabbing()
    return MV_CC_StartGrabbing(m_hDevHandle);
// ch:停止抓图 | en:Stop Grabbing
int CMvCamera::StopGrabbing()
    return MV_CC_StopGrabbing(m_hDevHandle);
// ch:主动获取一帧图像数据 | en:Get one frame initiatively
int CMvCamera::GetImageBuffer(MV_FRAME_OUT* pFrame, int nMsec)
    return MV_CC_GetImageBuffer(m_hDevHandle, pFrame, nMsec);
// ch:释放图像缓存 | en:Free image buffer
int CMvCamera::FreeImageBuffer(MV_FRAME_OUT* pFrame)
    return MV_CC_FreeImageBuffer(m_hDevHandle, pFrame);
// ch:设置显示窗口句柄 | en: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::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);
int CMvCamera::GetEnumEntrySymbolic(IN const char* strKey, IN MVCC_ENUMENTRY* pstEnumEntry)
    return MV_CC_GetEnumEntrySymbolic(m_hDevHandle, strKey, pstEnumEntry);
// 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);
// ch:绘制圆形辅助线 | en:Draw circle auxiliary line
int CMvCamera::DrawCircle(MVCC_CIRCLE_INFO* pCircleInfo)
    return MV_CC_DrawCircle(m_hDevHandle, pCircleInfo);
// ch:绘制线形辅助线 | en:Draw lines auxiliary line
int CMvCamera::DrawLines(MVCC_LINES_INFO* pLinesInfo)
    return MV_CC_DrawLines(m_hDevHandle, pLinesInfo);
//读取相机中的图像
int CMvCamera::ReadBuffer(Mat &image)
    Mat* getImage = new 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, 700);
    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 = Mat(stImageInfo.nHeight,stImageInfo.nWidth,CV_8UC1,pDate);
        //imwrite("d:\\测试opencv_Mono.tif", image);
        //转换图像格式为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 = Mat(stImageInfo.nHeight,stImageInfo.nWidth,CV_8UC3,m_pBufForSaveImage);
        //imwrite("d:\\测试opencv_Color.tif", image);
    (*getImage).copyTo(image);
    (*getImage).release();
    free(pDate);
    free(m_pBufForSaveImage);
    return 0;

3.mythread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QThread>
#include <QImage>
#include <QDir>
#include <QDateTime>
#include <QDebug>
#include "cmvcamera.h"
class MyThread : public QThread
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = nullptr);
     ~MyThread();
    void run();
    void getCameraPtr(CMvCamera *camera);
    void getImagePtr(cv::Mat *image);
signals:
    void signal_message();
    void signal_messImage(QImage myImage);
private:
    CMvCamera *cameraPtr = NULL;
    cv::Mat *imagePtr = NULL;
    QImage *myImage = NULL;
#endif // MYTHREAD_H

4.mythread.cpp

#include "mythread.h"
MyThread::MyThread(QObject *parent)
    : QThread{parent}
    myImage = new QImage();
MyThread::~MyThread()
    delete myImage;
    if(cameraPtr == NULL)
        delete cameraPtr;
    if(imagePtr == NULL)
        delete imagePtr;
void MyThread::getCameraPtr(CMvCamera *camera)
    cameraPtr = camera;
void MyThread::getImagePtr(cv::Mat *image)
    imagePtr = image;
void MyThread::run()
    if(cameraPtr == NULL)
        return;
    if(imagePtr == NULL)
        return;
    while(!isInterruptionRequested())
        qDebug()<<"SoftTrigger:"<<cameraPtr->CommandExecute("TriggerSoftware");
        qDebug()<<"ReadBuffer:"<<cameraPtr->ReadBuffer(*imagePtr);
        //先发送好再处理
        //emit signal_message();
        //msleep(10);
        //先处理好再发送
        if(imagePtr->channels()>1)
            *myImage = QImage((const unsigned char*)(imagePtr->data),imagePtr->cols,imagePtr->rows,QImage::Format_RGB888);
            *myImage = QImage((const unsigned char*)(imagePtr->data),imagePtr->cols,imagePtr->rows,QImage::Format_Indexed8);
        emit signal_messImage(*myImage);
        msleep(10);
        //耗时操作,需要放到线程中保存
        //QImage保存图像
        //QString savePath = QDir::currentPath() + "/myImage/";
        //QString curDate = QDateTime::currentDateTime().toString("yyyyMMdd-hhmmss.zzz");
        //QString saveName = savePath + curDate + ".png";
        //qDebug()<<"saveName:"<<saveName;
        //myImage->save(saveName);

5.widget.h

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QMessageBox>
#include "cmvcamera.h"
#include "mythread.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    void initWidget();
    void saveImage(QString format);
    void display(const Mat* image);
private slots:
    void slot_display();
    void slot_displayImage(QImage myImage);
    void on_pb_find_clicked();
    void on_pb_open_clicked();
    void on_pb_close_clicked();
    void on_pb_single_clicked();
    void on_pb_start_clicked();
    void on_pb_stop_clicked();
    void on_pb_saveBmp_clicked();
    void on_pb_savePng_clicked();
private:
    Ui::Widget *ui;
    bool m_bOpenDevice;
    MV_CC_DEVICE_INFO_LIST m_stDevList;
    CMvCamera *m_pcMyCamera = NULL;
    MyThread *myThread = NULL;
    Mat *myImage = NULL;
#endif // WIDGET_H

6.widget.cpp

#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    ui->setupUi(this);
    initWidget();
Widget::~Widget()
    delete ui;
    delete myImage;
    if(m_pcMyCamera)
        m_pcMyCamera->Close();
        delete m_pcMyCamera;
        m_pcMyCamera = NULL;
    if(myThread->isRunning())
        myThread->requestInterruption();
        myThread->wait();
        delete myThread;
void Widget::initWidget()
    //设置窗口属性
    this->setWindowTitle("相机测试");
    this->setWindowFlags(Qt::WindowCloseButtonHint | Qt::Dialog);
    this->setWindowModality(Qt::ApplicationModal);
    this->setFixedSize(this->width(),this->height());
    //初始化变量
    m_bOpenDevice = false;
    //生成保存图片的文件夹
    QString imagePath = QDir::currentPath() + "/myImage/";
    QDir dstDir(imagePath);
    if(!dstDir.exists())
        if(!dstDir.mkdir(imagePath))
            qDebug()<<"创建Image文件夹失败!";
            //return;
    //图像指针对象
    myImage = new Mat();
    //线程对象实例化
    myThread = new MyThread();
    connect(myThread,SIGNAL(signal_message()),this,SLOT(slot_display()));
    connect(myThread,SIGNAL(signal_messImage(QImage)),this,SLOT(slot_displayImage(QImage)));
//保存图片
void Widget::saveImage(QString format)
    if(ui->lb_show->pixmap() == NULL)
        QMessageBox::warning(this,"警告","保存失败,未采集到图像!");
        return;
    //QPixmap方法保存在程序运行目录
    //format: .bmp .tif .png .jpg
    QString savePath = QDir::currentPath() + "/myImage/";
    QString curDate = QDateTime::currentDateTime().toString("yyyyMMdd-hhmmss.zzz");
    QString saveName = savePath + curDate + "." + format;
    const QPixmap *curImage = ui->lb_show->pixmap();
    qDebug()<<"saveName:"<<saveName;
    if(curImage->save(saveName))
        qDebug()<<"保存成功!";
        qDebug()<<"保存失败!";
//用于显示单张图像
void Widget::display(const Mat* imagePtr)
    qDebug()<<"single display ok";
    //判断是黑白、彩色图像
    QImage* QmyImage = new QImage();
    if(imagePtr->channels()>1)
        *QmyImage = QImage((const unsigned char*)(imagePtr->data),imagePtr->cols,imagePtr->rows,QImage::Format_RGB888);
        *QmyImage = QImage((const unsigned char*)(imagePtr->data),imagePtr->cols,imagePtr->rows,QImage::Format_Indexed8);
    *QmyImage = (*QmyImage).scaled(ui->lb_show->size(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
    //QImage保存图像
    //QmyImage->save(saveName);
    //显示图像
    ui->lb_show->setPixmap(QPixmap::fromImage(*QmyImage));
    delete QmyImage;
void Widget::slot_display()
    qDebug()<<"continuous display ok";
    //判断是黑白、彩色图像
    QImage *QmyImage = new QImage();
    if(myImage->channels()>1)
        *QmyImage = QImage((const unsigned char*)(myImage->data),myImage->cols,myImage->rows,QImage::Format_RGB888);
        *QmyImage = QImage((const unsigned char*)(myImage->data),myImage->cols,myImage->rows,QImage::Format_Indexed8);
    *QmyImage = (*QmyImage).scaled(ui->lb_show->size(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
    //显示图像
    ui->lb_show->setPixmap(QPixmap::fromImage(*QmyImage));
    delete QmyImage;
void Widget::slot_displayImage(QImage myImage)
    //显示图像
    //QSize imageSize = QSize(400,400);
    //可以使用imageSize代替ui->lb_show->size(),固定图片显示窗口的大小,解决布局情况下图像窗口逐渐变大的bug。
    myImage = (myImage).scaled(ui->lb_show->size(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
    ui->lb_show->setPixmap(QPixmap::fromImage(myImage));
void Widget::on_pb_find_clicked()
    ui->cb_devices->clear();
    memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
    //枚举子网内所有设备
    int nRet = CMvCamera::EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE,&m_stDevList);
    if (MV_OK != nRet)
        return;
    for(unsigned int i = 0; i < m_stDevList.nDeviceNum; i++)
        MV_CC_DEVICE_INFO* pDeviceInfo = m_stDevList.pDeviceInfo[i];
        QString strModelName = "";
        if(pDeviceInfo->nTLayerType == MV_USB_DEVICE)
            strModelName = (char*)pDeviceInfo->SpecialInfo.stUsb3VInfo.chModelName;
        else if(pDeviceInfo->nTLayerType == MV_GIGE_DEVICE)
            strModelName = (char*)pDeviceInfo->SpecialInfo.stGigEInfo.chModelName;
            QMessageBox::warning(this,"警告","未知设备枚举!");
            return;
        qDebug()<<"strModelName:"<<strModelName;
        ui->cb_devices->addItem(strModelName);
void Widget::on_pb_open_clicked()
    if(m_bOpenDevice)
        return;
    QString deviceModel = ui->cb_devices->currentText();
    if(deviceModel == "")
        QMessageBox::warning(this,"警告","请选择设备!");
        return;
    m_pcMyCamera = new CMvCamera;
    if(NULL == m_pcMyCamera)
        return;
    int nIndex = ui->cb_devices->currentIndex();
    //打开设备
    int nRet = m_pcMyCamera->Open(m_stDevList.pDeviceInfo[nIndex]);
    qDebug()<<"Connect:"<<nRet;
    if(MV_OK != nRet)
        delete m_pcMyCamera;
        m_pcMyCamera = NULL;
        QMessageBox::warning(this,"警告","打开设备失败!");
        return;
    //设置为触发模式
    qDebug()<<"TriggerMode:"<<m_pcMyCamera->SetEnumValue("TriggerMode",1);
    //设置触发源为软触发
    qDebug()<<"TriggerSource:"<<m_pcMyCamera->SetEnumValue("TriggerSource",7);
    //设置曝光时间
    qDebug()<<"SetExposureTime:"<<m_pcMyCamera->SetFloatValue("ExposureTime",5000);
    //开启相机采集
    qDebug()<<"StartCamera:"<<m_pcMyCamera->StartGrabbing();
    myThread->getCameraPtr(m_pcMyCamera);
    myThread->getImagePtr(myImage);
    m_bOpenDevice = true;
void Widget::on_pb_close_clicked()
    if(m_pcMyCamera)
        m_pcMyCamera->Close();
        delete m_pcMyCamera;
        m_pcMyCamera = NULL;
        m_bOpenDevice = false;
void Widget::on_pb_single_clicked()
    if(!m_bOpenDevice)
        QMessageBox::warning(this,"警告","采集失败,请打开设备!");
        return;
    Mat *image = new Mat();
    //发送软触发
    qDebug()<<"single SoftTrigger:"<<m_pcMyCamera->CommandExecute("TriggerSoftware");
    //读取Mat格式的图像
    qDebug()<<"single ReadBuffer:"<<m_pcMyCamera->ReadBuffer(*image);
    display(image);
    //释放指针
    delete image;
void Widget::on_pb_start_clicked()
    if(!m_bOpenDevice)
        QMessageBox::warning(this,"警告","采集失败,请打开设备!");
        return;
    if(!myThread->isRunning())
        myThread->start();
void Widget::on_pb_stop_clicked()
    if(myThread->isRunning())
        myThread->requestInterruption();
        myThread->wait();
void Widget::on_pb_saveBmp_clicked()
    saveImage("bmp");   //文件较大
void Widget::on_pb_savePng_clicked()
    saveImage("png");   //文件较小

7.widget.ui

8.完整代码百度网盘链接 链接:pan.baidu.com/s/1bs59hJz1… 提取码:xxcj

四、问题解决

1.error: '__int64' does not name a type; did you mean '__divtc3'? typedef __int64 int64_t; 解决方法: 进入PixelType.h文件,修改Line:181 #define __int64 long long

2.error: reference to 'ACCESS_MASK' is ambiguous typedef ACCESS_MASK *PACCESS_MASK; 解决方法: 将头文件中的“using namespac cv;”屏蔽或删除, 然后在相应的函数或者数据类型加上前缀“cv::” 如:“cv::Mat”

这个示例相较于海康提供的demo也是少了几个设置参数的功能,实现的也比较简单,其中图像保存使用了qt中的QPixmap方法保存在程序运行目录,另外一些前期的准备工作没有写在本文中,具体的可以查看下列参考博客。

hello: 共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。

参考博客:手把手带你模仿 海康威视sdk+Qt 的二次开发(下) 海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(二)

  • 私信
     
    推荐文章