系列文章目录
提示:这里是该系列文章的所有文章的目录
第一章: (一)Qt+OpenCV调用海康工业相机SDK示例开发
第二章: (二)Qt多线程实现海康工业相机图像实时采集
文章目录
系列文章目录前言一、环境配置二、项目准备三、示例完整代码展示/下载链接四、问题解决总结前言
近期在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文件中添加下列代码:
#OpenCVINCLUDEPATH += $$PWD/OpenCV/IncludesLIBS += -L $$PWD/OpenCV/Lib/libopencv_*.a#SDKINCLUDEPATH += $$PWD/SDK/IncludesDEPENDPATH += $$PWD/SDK/IncludesLIBS += -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#endifclass CMvCamera{public:CMvCamera();~CMvCamera();// ch:获取SDK版本号 | en:Get SDK Versionstatic int GetSDKVersion();// ch:枚举设备 | en:Enumerate Devicestatic int EnumDevices(unsigned int nTLayerType, MV_CC_DEVICE_INFO_LIST* pstDevList);// ch:判断设备是否可达 | en:Is the device accessiblestatic bool IsDeviceAccessible(MV_CC_DEVICE_INFO* pstDevInfo, unsigned int nAccessMode);// ch:打开设备 | en:Open Deviceint Open(MV_CC_DEVICE_INFO* pstDeviceInfo);// ch:关闭设备 | en:Close Deviceint Close();// ch:判断相机是否处于连接状态 | en:Is The Device Connectedbool IsDeviceConnected();// ch:注册图像数据回调 | en:Register Image Data CallBackint RegisterImageCallBack(void(__stdcall* cbOutput)(unsigned char * pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser), void* pUser);// ch:开启抓图 | en:Start Grabbingint StartGrabbing();// ch:停止抓图 | en:Stop Grabbingint StopGrabbing();// ch:主动获取一帧图像数据 | en:Get one frame initiativelyint GetImageBuffer(MV_FRAME_OUT* pFrame, int nMsec);// ch:释放图像缓存 | en:Free image bufferint FreeImageBuffer(MV_FRAME_OUT* pFrame);// ch:显示一帧图像 | en:Display one frame imageint DisplayOneFrame(MV_DISPLAY_FRAME_INFO* pDisplayInfo);// ch:设置SDK内部图像缓存节点个数 | en:Set the number of the internal image cache nodes in SDKint SetImageNodeNum(unsigned int nNum);// ch:获取设备信息 | en:Get device informationint GetDeviceInfo(MV_CC_DEVICE_INFO* pstDevInfo);// ch:获取GEV相机的统计信息 | en:Get detect info of GEV cameraint GetGevAllMatchInfo(MV_MATCH_INFO_NET_DETECT* pMatchInfoNetDetect);// ch:获取U3V相机的统计信息 | en:Get detect info of U3V cameraint 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 directoryint 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 directoryint 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 directoryint 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 directoryint 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 directoryint 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 directoryint 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 CallBackint RegisterExceptionCallBack(void(__stdcall* cbException)(unsigned int nMsgType, void* pUser), void* pUser);// ch:注册单个事件回调 | en:Register Event CallBackint RegisterEventCallBack(const char* pEventName, void(__stdcall* cbEvent)(MV_EVENT_OUT_INFO * pEventInfo, void* pUser), void* pUser);// ch:强制IP | en:Force IPint ForceIp(unsigned int nIP, unsigned int nSubNetMask, unsigned int nDefaultGateWay);// ch:配置IP方式 | en:IP configuration methodint SetIpConfig(unsigned int nType);// ch:设置网络传输模式 | en:Set Net Transfer Modeint SetNetTransMode(unsigned int nType);// ch:像素格式转换 | en:Pixel format conversionint ConvertPixelType(MV_CC_PIXEL_CONVERT_PARAM* pstCvtParam);// ch:保存图片 | en:save imageint SaveImage(MV_SAVE_IMAGE_PARAM_EX* pstParam);// ch:保存图片为文件 | en:Save the image as a fileint SaveImageToFile(MV_SAVE_IMG_TO_FILE_PARAM* pstParam);// ch:绘制圆形辅助线 | en:Draw circle auxiliary lineint DrawCircle(MVCC_CIRCLE_INFO* pCircleInfo);// ch:绘制线形辅助线 | en:Draw lines auxiliary lineint DrawLines(MVCC_LINES_INFO* pLinesInfo);//读取bufferint 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 Versionint CMvCamera::GetSDKVersion(){return MV_CC_GetSDKVersion();}// ch:枚举设备 | en:Enumerate Deviceint CMvCamera::EnumDevices(unsigned int nTLayerType, MV_CC_DEVICE_INFO_LIST* pstDevList){return MV_CC_EnumDevices(nTLayerType, pstDevList);}// ch:判断设备是否可达 | en:Is the device accessiblebool CMvCamera::IsDeviceAccessible(MV_CC_DEVICE_INFO* pstDevInfo, unsigned int nAccessMode){return MV_CC_IsDeviceAccessible(pstDevInfo, nAccessMode);}// ch:打开设备 | en:Open Deviceint 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 Deviceint 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 Connectedbool CMvCamera::IsDeviceConnected(){return MV_CC_IsDeviceConnected(m_hDevHandle);}// ch:注册图像数据回调 | en:Register Image Data CallBackint 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 Grabbingint CMvCamera::StartGrabbing(){return MV_CC_StartGrabbing(m_hDevHandle);}// ch:停止抓图 | en:Stop Grabbingint CMvCamera::StopGrabbing(){return MV_CC_StopGrabbing(m_hDevHandle);}// ch:主动获取一帧图像数据 | en:Get one frame initiativelyint CMvCamera::GetImageBuffer(MV_FRAME_OUT* pFrame, int nMsec){return MV_CC_GetImageBuffer(m_hDevHandle, pFrame, nMsec);}// ch:释放图像缓存 | en:Free image bufferint CMvCamera::FreeImageBuffer(MV_FRAME_OUT* pFrame){return MV_CC_FreeImageBuffer(m_hDevHandle, pFrame);}// ch:设置显示窗口句柄 | en:Set Display Window Handleint 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 SDKint CMvCamera::SetImageNodeNum(unsigned int nNum){return MV_CC_SetImageNodeNum(m_hDevHandle, nNum);}// ch:获取设备信息 | en:Get device informationint CMvCamera::GetDeviceInfo(MV_CC_DEVICE_INFO* pstDevInfo){return MV_CC_GetDeviceInfo(m_hDevHandle, pstDevInfo);}// ch:获取GEV相机的统计信息 | en:Get detect info of GEV cameraint 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 cameraint 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 directoryint 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 directoryint 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 directoryint 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 directoryint 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 directoryint 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 directoryint 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 CallBackint CMvCamera::RegisterExceptionCallBack(void(__stdcall* cbException)(unsigned int nMsgType, void* pUser),void* pUser){return MV_CC_RegisterExceptionCallBack(m_hDevHandle, cbException, pUser);}// ch:注册单个事件回调 | en:Register Event CallBackint 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 IPint 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 methodint CMvCamera::SetIpConfig(unsigned int nType){return MV_GIGE_SetIpConfig(m_hDevHandle, nType);}// ch:设置网络传输模式 | en:Set Net Transfer Modeint CMvCamera::SetNetTransMode(unsigned int nType){return MV_GIGE_SetNetTransMode(m_hDevHandle, nType);}// ch:像素格式转换 | en:Pixel format conversionint CMvCamera::ConvertPixelType(MV_CC_PIXEL_CONVERT_PARAM* pstCvtParam){return MV_CC_ConvertPixelType(m_hDevHandle, pstCvtParam);}// ch:保存图片 | en:save imageint CMvCamera::SaveImage(MV_SAVE_IMAGE_PARAM_EX* pstParam){return MV_CC_SaveImageEx2(m_hDevHandle, pstParam);}// ch:保存图片为文件 | en:Save the image as a fileint CMvCamera::SaveImageToFile(MV_SAVE_IMG_TO_FILE_PARAM* pstSaveFileParam){return MV_CC_SaveImageToFile(m_hDevHandle, pstSaveFileParam);}// ch:绘制圆形辅助线 | en:Draw circle auxiliary lineint CMvCamera::DrawCircle(MVCC_CIRCLE_INFO* pCircleInfo){return MV_CC_DrawCircle(m_hDevHandle, pCircleInfo);}// ch:绘制线形辅助线 | en:Draw lines auxiliary lineint 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);}else{//转换图像格式为BGR8MV_CC_PIXEL_CONVERT_PARAM stConvertParam = {0};memset(&stConvertParam, 0, sizeof(MV_CC_PIXEL_CONVERT_PARAM));stConvertParam.nWidth = stImageInfo.nWidth; //ch:图像宽 | en:image widthstConvertParam.nHeight = stImageInfo.nHeight;//ch:图像高 | en:image height//stConvertParam.pSrcData = m_pBufForDriver; //ch:输入数据缓存 | en:input data bufferstConvertParam.pSrcData = pDate; //ch:输入数据缓存 | en:input data bufferstConvertParam.nSrcDataLen = stImageInfo.nFrameLen; //ch:输入数据大小 | en:input data sizestConvertParam.enSrcPixelType = stImageInfo.enPixelType; //ch:输入像素格式 | en:input pixel formatstConvertParam.enDstPixelType = PixelType_Gvsp_BGR8_Packed; //ch:输出像素格式 | en:output pixel format 适用于OPENCV的图像格式//stConvertParam.enDstPixelType = PixelType_Gvsp_RGB8_Packed; //ch:输出像素格式 | en:output pixel formatstConvertParam.pDstBuffer = m_pBufForSaveImage;//ch:输出数据缓存 | en:output data bufferstConvertParam.nDstBufferSize = m_nBufSizeForSaveImage; //ch:输出缓存大小 | en:output buffer sizeMV_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_OBJECTpublic: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);}else{*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_NAMESPACEnamespace Ui {class Widget; }QT_END_NAMESPACEclass Widget : public QWidget{Q_OBJECTpublic: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 .jpgQString 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()<<"保存成功!";}else{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);}else{*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);}else{*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;}else{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.完整代码百度网盘链接
链接:/s/1bs59hJz155NP3aQMnqCDSA
提取码: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++)(二)