系列文章目录

提示:这里是该系列文章的所有文章的目录 第一章: (一)Qt+OpenCV调用海康工业相机SDK示例开发 第二章: (二)Qt多线程实现海康工业相机图像实时采集 第三章: (三)Qt+OpenCV调用海康工业相机SDK抓拍示例

文章目录

系列文章目录前言一、项目配置二、图像采集与保存三、示例完整代码总结

前言

在这系列文章中,讲述了Qt下结合OpenCV与海康工业相机的使用,对前文的功能进行拓展,在这里做了一个使用海康彩色工业相机定时抓拍的示例,并将相关代码展现出来以便大家学习,如有错误之处,欢迎大家批评指正。

项目效果

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

一、项目配置

本文示例是在MSVC_64bit下Release构建的,然后引入了海康SDK和OpenCV对应的库,所以项目的pro文件如下: MyCamera.pro

QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

DEFINES += QT_DEPRECATED_WARNINGS

#设置字符

contains( CONFIG,"msvc" ):QMAKE_CXXFLAGS += /source-charset:utf-8 /execution-charset:utf-8

contains( CONFIG,"msvc" ):QMAKE_CFLAGS +=/source-charset:utf-8 /execution-charset:utf-8

SOURCES += \

capturethread.cpp \

cmvcamera.cpp \

main.cpp \

widget.cpp

HEADERS += \

capturethread.h \

cmvcamera.h \

widget.h

FORMS += \

widget.ui

# Default rules for deployment.

qnx: target.path = /tmp/$${TARGET}/bin

else: unix:!android: target.path = /opt/$${TARGET}/bin

!isEmpty(target.path): INSTALLS += target

#HikSDK

INCLUDEPATH += $$PWD/SDK/HikSDK/Includes

DEPENDPATH += $$PWD/SDK/HikSDK/Includes

LIBS += -L$$PWD/SDK/HikSDK/Lib/ -lMvCameraControl

#OpenCV

INCLUDEPATH += $$PWD/SDK/OpenCV/Includes

DEPENDPATH += $$PWD/SDK/OpenCV/Includes

LIBS += -L$$PWD/SDK/OpenCV/Lib/ -lopencv_world455

二、图像采集与保存

示例采集的原理: //点击开始采集后,会关闭触发模式,相机就会不断回调,实时显示相机图像 //点击停止采集后,会开启触发模式并设置为软触发,需要调用命令触发回调

在设备打开后,通过点击抓拍按钮开启线程并打开保存标志位,在线程中使用OpenCV的imwrite函数来进行图像的保存。

//抓拍图像

void Widget::on_pb_grab_clicked()

{

if(!m_bOpenDevice)

{

QMessageBox::warning(this,"警告","抓拍失败,请打开设备!");

return;

}

int time = ui->le_time->text().toInt();

int num = ui->le_num->text().toInt();

m_captureThread->setCameraSignal(time,num);

m_captureThread->setSwitchFlag(true);

m_captureThread->setSaveFlag(true);

m_captureThread->start();

}

......

//保存原图

void CaptureThread::saveOriginImage(cv::Mat imageMat)

{

clock_t originClock = -clock();

QString curTime = QTime::currentTime().toString("hhmmss");

QString iamgeName = m_originPath + "GrabImage_" + curTime + ".jpg";

cv::Mat saveMat;

cvtColor(imageMat,saveMat,cv::COLOR_BGR2RGB); //颜色格式转换

imwrite(iamgeName.toStdString(),saveMat);

originClock += clock();

LOGDEBUG<<"保存原图耗时:"<

}

三、示例完整代码

示例的功能实现就不多说了,在下面的代码中有详细的注释,这里将完整代码展示出来: 1.cmvcamera.h(直接从海康提供的SDK中复制,进行了一些修改)

/************************************************************************/

/* 以C++接口为基础,对常用函数进行二次封装,方便用户使用 */

/************************************************************************/

#ifndef _MV_CAMERA_H_

#define _MV_CAMERA_H_

#include

#include

#include "MvCameraControl.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:注册彩色图像数据回调

int RegisterImageCallBackRGB(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);

//读取相机中的图像

int ReadBuffer(cv::Mat &image);

//保存相机中的图像

int SaveBuffer(QByteArray imageName);

private:

void *m_hDevHandle;

};

#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:注册彩色图像数据回调

int CMvCamera::RegisterImageCallBackRGB(void(__stdcall* cbOutput)(unsigned char * pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser), void* pUser)

{

return MV_CC_RegisterImageCallBackForRGB(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(cv::Mat &image)

{

unsigned int nRecvBufSize = 0;

MVCC_INTVALUE_EX stParam;

memset(&stParam,0,sizeof(MVCC_INTVALUE_EX));

int nRet = GetIntValue("PayloadSize",&stParam);

if(MV_OK != nRet)

{

return nRet;

}

nRecvBufSize = stParam.nCurValue;

unsigned char* pDate;

pDate = (unsigned char *)malloc(nRecvBufSize);

MV_FRAME_OUT_INFO_EX stImageInfo;

memset(&stImageInfo,0,sizeof(MV_FRAME_OUT_INFO));

nRet = MV_CC_GetOneFrameTimeout(m_hDevHandle,pDate,nRecvBufSize,&stImageInfo,500);

if(MV_OK != nRet)

{

return nRet;

}

//用于保存图像的缓存

unsigned int nBufSizeForSaveImage = stImageInfo.nWidth * stImageInfo.nHeight * 3 + 2048;

unsigned char* pBufForSaveImage = (unsigned char*)malloc(nBufSizeForSaveImage);

//判断是否为黑白图像

bool isMono;

cv::Mat getImage;

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); //单色

}

else

{

//转换图像格式为RGB8

MV_CC_PIXEL_CONVERT_PARAM stConvertParam;

memset(&stConvertParam,0,sizeof(MV_CC_PIXEL_CONVERT_PARAM));

stConvertParam.nWidth = stImageInfo.nWidth;

stConvertParam.nHeight = stImageInfo.nHeight;

stConvertParam.pSrcData = pDate; //输入数据缓存

stConvertParam.nSrcDataLen = stImageInfo.nFrameLen;

stConvertParam.enSrcPixelType = stImageInfo.enPixelType;

//stConvertParam.enDstPixelType = PixelType_Gvsp_BGR8_Packed; //输出像素格式

stConvertParam.enDstPixelType = PixelType_Gvsp_RGB8_Packed;

stConvertParam.pDstBuffer = pBufForSaveImage; //输出数据缓存

stConvertParam.nDstBufferSize = nBufSizeForSaveImage; //输出缓存大小

MV_CC_ConvertPixelType(m_hDevHandle, &stConvertParam);

getImage = cv::Mat(stImageInfo.nHeight,stImageInfo.nWidth,CV_8UC3,pBufForSaveImage);

}

getImage.copyTo(image);

getImage.release();

free(pDate);

free(pBufForSaveImage);

return MV_OK;

}

//读取保存相机中的图像

int CMvCamera::SaveBuffer(QByteArray imageName)

{

unsigned int nRecvBufSize = 0;

MVCC_INTVALUE_EX stParam;

memset(&stParam,0,sizeof(MVCC_INTVALUE_EX));

int nRet = GetIntValue("PayloadSize",&stParam); //获取Integer属性值

if(MV_OK != nRet)

{

return nRet;

}

nRecvBufSize = stParam.nCurValue;

unsigned char* pDate;

pDate = (unsigned char *)malloc(nRecvBufSize);

MV_FRAME_OUT_INFO_EX stImageInfo;

memset(&stImageInfo,0,sizeof(MV_FRAME_OUT_INFO));

nRet = MV_CC_GetOneFrameTimeout(m_hDevHandle,pDate,nRecvBufSize,&stImageInfo,500); //采用超时机制获取一帧图片

if(MV_OK != nRet)

{

return nRet;

}

MV_SAVE_IMG_TO_FILE_PARAM stSaveFileParam;

memset(&stSaveFileParam,0,sizeof(MV_SAVE_IMG_TO_FILE_PARAM));

stSaveFileParam.enImageType = MV_Image_Bmp;

stSaveFileParam.enPixelType = stImageInfo.enPixelType;

stSaveFileParam.nWidth = stImageInfo.nWidth;

stSaveFileParam.nHeight = stImageInfo.nHeight;

stSaveFileParam.nDataLen = stImageInfo.nFrameLen;

stSaveFileParam.pData = pDate;

stSaveFileParam.iMethodValue = 0;

sprintf_s(stSaveFileParam.pImagePath,256,imageName.data()); //文件名

nRet = SaveImageToFile(&stSaveFileParam); //保存图片为文件

if(MV_OK != nRet)

{

return nRet;

}

free(pDate);

return MV_OK;

}

3.capturethread.h

#ifndef CAPTURETHREAD_H

#define CAPTURETHREAD_H

#include

#include

#include

#include

#include

#include

#include

#include

#include "cmvcamera.h"

#define LOGDEBUG qDebug()<

class CaptureThread : public QThread

{

Q_OBJECT

public:

explicit CaptureThread(QObject *parent = nullptr);

~CaptureThread();

void initThread();

void setCameraPtr(CMvCamera *camera);

void setCameraSignal(int time,int num);

void setSavePath(QString originPath);

void setSaveFlag(bool saveFlag);

void setSwitchFlag(bool switchFlag);

void setSoftModeFlag(bool softModeFlag);

void setImageBuffer(cv::Mat imageMat);

void run();

QImage cvMatToImage(const cv::Mat imageMat);

void saveOriginImage(cv::Mat imageMat);

signals:

void signal_newImage(QImage newImage);

private:

static void __stdcall ImageCallback(unsigned char * pData,MV_FRAME_OUT_INFO_EX* pFrameInfo,void* pUser);

private:

CMvCamera *m_cameraPtr = NULL;

int m_imageTime; //抓拍间隔时间

int m_imageNum; //抓拍间隔次数

QString m_originPath; //原图保存路径

bool m_saveFlag; //保存图像标志

bool m_switchFlag; //线程开启标志

bool m_softModeFlag; //软触发模式标志

};

#endif // CAPTURETHREAD_H

4.capturethread.cpp

#include "capturethread.h"

CaptureThread::CaptureThread(QObject *parent)

: QThread{parent}

{

this->initThread();

}

CaptureThread::~CaptureThread()

{

}

//初始化图像捕获线程

void CaptureThread::initThread()

{

m_imageTime = 1000;

m_imageNum = 1;

m_originPath = "";

m_saveFlag = false;

m_switchFlag = false;

m_softModeFlag = false;

}

//设置相机指针

void CaptureThread::setCameraPtr(CMvCamera *camera)

{

m_cameraPtr = camera;

//注册回调函数

int nRet = m_cameraPtr->RegisterImageCallBackRGB(ImageCallback,this); //彩色相机

if(MV_OK != nRet)

{

LOGDEBUG<<"相机注册回调函数失败";

}

else

{

LOGDEBUG<<"相机注册回调函数成功";

}

}

//设置相机拍照间隔时间和次数

void CaptureThread::setCameraSignal(int time,int num)

{

m_imageTime = time*1000;

m_imageNum = num;

if(m_imageTime <= 0)

{

m_imageTime = 1000;

}

if(m_imageNum <= 0)

{

m_imageNum = 1;

}

}

//设置图像保存路径

void CaptureThread::setSavePath(QString originPath)

{

m_originPath = originPath;

LOGDEBUG<<"相机原图保存路径:"<

}

//设置是否保存图像

void CaptureThread::setSaveFlag(bool saveFlag)

{

m_saveFlag = saveFlag;

}

//设置线程开关

void CaptureThread::setSwitchFlag(bool switchFlag)

{

m_switchFlag = switchFlag;

}

//设置软触发

void CaptureThread::setSoftModeFlag(bool softModeFlag)

{

m_softModeFlag = softModeFlag;

}

//获取回调返回的图像

void CaptureThread::setImageBuffer(cv::Mat imageMat)

{

LOGDEBUG<<"获取回调图像";

if(m_saveFlag)

{

m_saveFlag = false;

saveOriginImage(imageMat);

}

emit signal_newImage(cvMatToImage(imageMat));

}

//线程运行

void CaptureThread::run()

{

static int startNum = 0;

while(m_switchFlag)

{

if(startNum < m_imageNum)

{

startNum++;

if(m_softModeFlag)

{

m_cameraPtr->CommandExecute("TriggerSoftware");

}

m_saveFlag = true;

}

else

{

startNum = 0;

m_switchFlag = false;

}

msleep(m_imageTime);

}

}

//cv::Mat转QImage

QImage CaptureThread::cvMatToImage(const cv::Mat imageMat)

{

//颜色转换,opencv默认的彩色图像的颜色空间是BGR

//cvtColor(imageMat,imageMat,cv::COLOR_BGR2RGB);

QImage myImage;

if(imageMat.channels() > 1)

{

myImage = QImage((const unsigned char*)(imageMat.data),imageMat.cols,imageMat.rows,QImage::Format_RGB888); //彩色图

}

else

{

myImage = QImage((const unsigned char*)(imageMat.data),imageMat.cols,imageMat.rows,QImage::Format_Indexed8); //灰度图

}

return myImage;

}

//保存原图

void CaptureThread::saveOriginImage(cv::Mat imageMat)

{

clock_t originClock = -clock();

QString curTime = QTime::currentTime().toString("hhmmss");

QString iamgeName = m_originPath + "GrabImage_" + curTime + ".jpg";

cv::Mat saveMat;

cvtColor(imageMat,saveMat,cv::COLOR_BGR2RGB); //颜色格式转换

imwrite(iamgeName.toStdString(),saveMat);

originClock += clock();

LOGDEBUG<<"保存原图耗时:"<

}

//回调函数

void __stdcall CaptureThread::ImageCallback(unsigned char * pData,MV_FRAME_OUT_INFO_EX* pFrameInfo,void* pUser)

{

//LOGDEBUG<<"回调触发";

CaptureThread* pThread = static_cast(pUser);

//创建cv::Mat对象

cv::Mat showMat(pFrameInfo->nHeight,pFrameInfo->nWidth,CV_8UC3,pData); //彩色

//将图像保存到容器中

pThread->setImageBuffer(showMat);

}

5.widget.h

#ifndef WIDGET_H

#define WIDGET_H

#include

#include

#include "capturethread.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();

private slots:

void slot_displayImage(QImage myImage);

void on_pb_find_clicked();

void on_pb_open_clicked();

void on_pb_close_clicked();

void on_pb_set_clicked();

void on_pb_start_clicked();

void on_pb_stop_clicked();

void on_pb_grab_clicked();

private:

Ui::Widget *ui;

bool m_bOpenDevice;

QSize m_showSize;

CaptureThread *m_captureThread;

MV_CC_DEVICE_INFO_LIST m_stDevList;

CMvCamera *m_pcMyCamera = NULL;

MV_SAVE_IAMGE_TYPE m_nSaveImageType = MV_Image_Bmp;

};

#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;

if(m_pcMyCamera)

{

m_pcMyCamera->Close();

delete m_pcMyCamera;

m_pcMyCamera = NULL;

}

}

//初始化

void Widget::initWidget()

{

//设置窗口属性

this->setWindowTitle("抓图测试");

ui->pb_close->setEnabled(false);

ui->pb_stop->setEnabled(false);

//初始化变量

m_bOpenDevice = false;

m_showSize = QSize(768,512);

//生成保存图片的文件夹

QString imagePath = QCoreApplication::applicationDirPath() + "/SaveImage/";

QDir dstDir(imagePath);

if(!dstDir.exists())

{

if(!dstDir.mkdir(imagePath))

{

LOGDEBUG<<"创建图像保存文件夹失败!";

}

else

{

LOGDEBUG<<"创建图像保存文件夹成功!";

}

}

//初始化线程

m_captureThread = new CaptureThread();

connect(m_captureThread,SIGNAL(signal_newImage(QImage)),this,SLOT(slot_displayImage(QImage)),Qt::BlockingQueuedConnection);

m_captureThread->setSavePath(imagePath);

}

//显示图像

void Widget::slot_displayImage(QImage myImage)

{

QPixmap newPixmap = QPixmap::fromImage(myImage).scaled(m_showSize,Qt::KeepAspectRatio,Qt::SmoothTransformation);

ui->lb_show->setPixmap(newPixmap);

}

//查找设备

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)

{

LOGDEBUG<<"设备枚举失败";

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;

}

LOGDEBUG<<"相机型号:"<

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;

//打开设备

int nIndex = ui->cb_devices->currentIndex();

int nRet = m_pcMyCamera->Open(m_stDevList.pDeviceInfo[nIndex]);

if(MV_OK != nRet)

{

delete m_pcMyCamera;

m_pcMyCamera = NULL;

QMessageBox::warning(this,"警告","打开设备失败!");

return;

}

else

{

LOGDEBUG<<"打开设备成功!";

}

//设置为触发模式,触发源为软触发

m_pcMyCamera->SetEnumValue("TriggerMode",1);

m_pcMyCamera->SetEnumValue("TriggerSource",7);

//设置曝光时间和增益

int exposureTime = ui->le_exposureTime->text().toInt();

int gain = ui->le_gain->text().toInt();

m_pcMyCamera->SetFloatValue("ExposureTime",exposureTime);

m_pcMyCamera->SetEnumValue("GainAuto",0);

m_pcMyCamera->SetFloatValue("Gain",gain);

//相机线程设置,注册回调

m_captureThread->setCameraPtr(m_pcMyCamera);

//开启相机采集

m_pcMyCamera->StartGrabbing();

//开启标志位

m_bOpenDevice = true;

//使能按键

ui->pb_find->setEnabled(false);

ui->pb_open->setEnabled(false);

ui->pb_close->setEnabled(true);

}

//关闭设备

void Widget::on_pb_close_clicked()

{

if(m_bOpenDevice)

{

m_bOpenDevice = false;

if(m_pcMyCamera)

{

m_pcMyCamera->Close();

delete m_pcMyCamera;

m_pcMyCamera = NULL;

}

}

//使能按键

ui->pb_find->setEnabled(true);

ui->pb_open->setEnabled(true);

ui->pb_close->setEnabled(false);

}

//设置

void Widget::on_pb_set_clicked()

{

if(!m_bOpenDevice)

{

QMessageBox::warning(this,"警告","设置失败,请打开设备!");

return;

}

int exposureTime = ui->le_exposureTime->text().toInt();

int gain = ui->le_gain->text().toInt();

//设置曝光时间

m_pcMyCamera->SetFloatValue("ExposureTime",exposureTime);

//设置增益前先把自动增益关闭,失败无需返回

m_pcMyCamera->SetEnumValue("GainAuto",0);

m_pcMyCamera->SetFloatValue("Gain",gain);

//设置显示宽度和高度

int showW = ui->le_w->text().toInt();

int showH = ui->le_h->text().toInt();

if(showW < 768)

{

showW = 768;

ui->le_w->setText("768");

}

if(showH < 512)

{

showH = 512;

ui->le_h->setText("512");

}

m_showSize = QSize(showW,showH);

}

//开始采集

//点击开始采集后,会关闭触发模式,相机就会不断回调,实时显示相机图像

void Widget::on_pb_start_clicked()

{

if(!m_bOpenDevice)

{

QMessageBox::warning(this,"警告","采集失败,请打开设备!");

return;

}

//不保存图像

m_captureThread->setSaveFlag(false);

//关闭触发模式

m_captureThread->setSoftModeFlag(false);

m_pcMyCamera->SetEnumValue("TriggerMode",0);

//使能按键

ui->pb_find->setEnabled(false);

ui->pb_open->setEnabled(false);

ui->pb_close->setEnabled(false);

ui->pb_start->setEnabled(false);

ui->pb_stop->setEnabled(true);

}

//停止采集

//点击停止采集后,会开启触发模式并设置为软触发,需要调用命令触发回调

void Widget::on_pb_stop_clicked()

{

if(!m_bOpenDevice)

{

QMessageBox::warning(this,"警告","采集失败,请打开设备!");

return;

}

//设置为触发模式,触发源为软触发

m_captureThread->setSoftModeFlag(true);

m_pcMyCamera->SetEnumValue("TriggerMode",1);

m_pcMyCamera->SetEnumValue("TriggerSource",7);

//使能按键

ui->pb_find->setEnabled(false);

ui->pb_open->setEnabled(false);

ui->pb_close->setEnabled(true);

ui->pb_start->setEnabled(true);

ui->pb_stop->setEnabled(false);

ui->pb_grab->setEnabled(true);

}

//抓拍图像

void Widget::on_pb_grab_clicked()

{

if(!m_bOpenDevice)

{

QMessageBox::warning(this,"警告","抓拍失败,请打开设备!");

return;

}

int time = ui->le_time->text().toInt();

int num = ui->le_num->text().toInt();

m_captureThread->setCameraSignal(time,num);

m_captureThread->setSwitchFlag(true);

m_captureThread->setSaveFlag(true);

m_captureThread->start();

}

7.widget.ui

总结

这个示例相较于前文,也是增加了下设置相机曝光时间和增益这两个参数的功能,可以看到也是比较简单的,主要是要了解相机SDK相关的接口,并且海康相机的相关文档和示例也是很详细的,类似这样的开发,我们首先要做的就是从文档中找答案~

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

好文链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。