(三)Qt+OpenCV调用海康工业相机SDK抓拍示例

系列文章目录

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


文章目录

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


前言

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

项目效果
请添加图片描述


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

一、项目配置

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

QT       += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++11DEFINES += 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-8SOURCES += \capturethread.cpp \cmvcamera.cpp \main.cpp \widget.cppHEADERS += \capturethread.h \cmvcamera.h \widget.hFORMS += \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<<"保存原图耗时:"<<originClock<<"ms";   //测试在20ms左右
}

三、示例完整代码

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

/************************************************************************/
/* 以C++接口为基础,对常用函数进行二次封装,方便用户使用                */
/************************************************************************/#ifndef _MV_CAMERA_H_
#define _MV_CAMERA_H_#include <string.h>
#include <QCoreApplication>
#include "MvCameraControl.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:注册彩色图像数据回调int RegisterImageCallBackRGB(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);//读取相机中的图像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{//转换图像格式为RGB8MV_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 <QObject>
#include <QThread>
#include <QImage>
#include <QDir>
#include <QTimer>
#include <QDate>
#include <QDateTime>
#include <QDebug>
#include "cmvcamera.h"#define LOGDEBUG qDebug()<<QTime::currentTime().toString("[hh:mm:ss:zzz]")class CaptureThread : public QThread
{Q_OBJECTpublic: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<<"相机原图保存路径:"<<m_originPath;
}//设置是否保存图像
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<<"保存原图耗时:"<<originClock<<"ms";   //测试在20ms左右
}//回调函数
void __stdcall CaptureThread::ImageCallback(unsigned char * pData,MV_FRAME_OUT_INFO_EX* pFrameInfo,void* pUser)
{//LOGDEBUG<<"回调触发";CaptureThread* pThread = static_cast<CaptureThread *>(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 <QWidget>
#include <QMessageBox>
#include "capturethread.h"QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic: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<<"相机型号:"<<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;//打开设备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:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/286257.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

命令模式(请求与具体实现解耦)

目录 前言 UML plantuml 类图 实战代码 模板 Command Invoker Receiver Client 前言 命令模式解耦了命令请求者&#xff08;Invoker&#xff09;和命令执行者&#xff08;receiver&#xff09;&#xff0c;使得 Invoker 不再直接引用 receiver&#xff0c;而是依赖于…

学习vue3第十一节(依赖注入:provide/inject)

本机介绍&#xff1a;provide/inject 注意&#xff1a;大家在看此小节时候&#xff0c;默认大家已经了解一些组件的使用方法 1、依赖注入的用途&#xff1a; 当嵌套层级多的时候&#xff0c;某个子组件需要较远层级的父组件数据时候&#xff0c;如果我们依然使用props 传递数…

数据挖掘与机器学习 1. 绪论

于高山之巅&#xff0c;方见大河奔涌&#xff1b;于群峰之上&#xff0c;便觉长风浩荡 —— 24.3.24 一、数据挖掘和机器学习的定义 1.数据挖掘的狭义定义 背景&#xff1a;大数据时代——知识贫乏 数据挖掘的狭义定义&#xff1a; 数据挖掘就是从大量的、不完全的、有噪声的、…

CI/CD实战-jenkins结合docker 5

实验准备&#xff1a; 在docker主机要下载git工具 禁掉key的校验 确保在立即构建项目时不会出现任何报错&#xff1a; 自动化构建docker镜像 在server3上安装docker-ce 修改内核参数 拷贝证书 添加默认仓库 添加harbor仓库的解析 测试拉取 登录harbor私有仓库 在jenkins安装d…

微服务day06 -- Elasticsearch的数据搜索功能。分别使用DSL和RestClient实现搜索

1.DSL查询文档 elasticsearch的查询依然是基于JSON风格的DSL来实现的。 1.1.DSL查询分类 Elasticsearch提供了基于JSON的DSL&#xff08;Domain Specific Language&#xff09;来定义查询。常见的查询类型包括&#xff1a; 查询所有&#xff1a;查询出所有数据&#xff0c;一…

linux用户管理1

linux系统可以多用户同时登录&#xff0c;在各自权限下做各自的事情 useradd添加普通用户&#xff0c;之后使用suusername切换用户 所有用户中&#xff0c;root用户权限最大&#xff0c;对应uid&#xff0c;gid均为0&#xff0c;uid为用户编号&#xff0c;gid为用户所在组编号…

AcWing 4609:火柴棍数字 ← 贪心算法

【题目来源】 https://www.acwing.com/problem/content/4612/【题目描述】 给定 n 个火柴棍&#xff0c;你可以用它们摆出数字 0∼9。 摆出每个数字所需要的具体火柴棍数量如下图所示&#xff1a; 请你用这些火柴棍摆成若干个数字&#xff0c;并把这些数字排成一排组成一个整数…

【数据结构和算法初阶(C语言)】二叉树的链式结构--前、中、后序遍历实现详解,节点数目计算及oj题目详解---二叉树学习日记③

目录 ​编辑 1.二叉树的链式存储 2.二叉树链式结构的实现 2.1树的创建 2.2二叉树的再理解 3.链式结构二叉树的遍历 3.1前序遍历实现&#xff1a; ​编辑 3.2中序遍历实现 3.3后序遍历 ​编辑 4.链式二叉树节点数目的计算 4.1 总节点个数的计算 错误代码1&#xff1a; 错误代…

使用git下载github/gitee仓库部分或单个文件的方法

前言 有些时候在github或者gitee仓库中我们只需要下载整个项目中的我门需要的那一部分文件夹或文件就行了&#xff0c;不需要下载所有的项目。这样可以节省很多流量和时间 步骤 1.建立一个新的 git 本地仓库 这里我在D:\test中初始化 命令&#xff1a; git init2.在本地仓…

【Yolov7】踩坑记录

#windows上调用cuda去 使用GPU来进行预测 -需要下载cudnn&#xff0c;cuDNN 9.0.0 Downloads | NVIDIA Developer -环境变量要配置 比如 &#xff1a; C:\Program Files\NVIDIA\CUDNN\v9.0\bin\11.8 C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.7\bin 也可…

学习笔记Day15:Shell脚本编程

Shell脚本编程 Linux系统环境 Linux系统的4个主要部分&#xff1a;内核、shell、文件系统和应用程序。 内核是操作系统的核心&#xff0c;决定系统性能和稳定性shell &#xff1a;一种应用程序&#xff0c;是用户和内核交互操作的接口&#xff0c;是套在内核外的壳&#xff…

Stable Diffusion 进阶教程 - 二次开发(制作您的文生图应用)

目录 1. 引言 2. 基于Rest API 开发 2.1 前置条件 2.2 代码实现 2.3 效果演示 2.4 常见错误 3. 总结 1. 引言 Stable Diffusion作为一种强大的文本到图像生成模型&#xff0c;已经在艺术、设计和创意领域引起了广泛的关注和应用。然而&#xff0c;对于许多开发者来说&#xff…

使用倒模耳机壳UV树脂胶液制作舞台监听耳返入耳式耳机壳推荐的材料和工艺流程?

推荐的材料和工艺流程如下&#xff1a; 材料&#xff1a; UV树脂胶液&#xff1a;选择适合倒模工艺的UV树脂胶液&#xff0c;要求具有高透明度、良好的流动性和固化性能。模具材料&#xff1a;建议使用硅胶模具&#xff0c;因为硅胶模具具有较高的耐用性和稳定性&#xff0c;…

Linux 安装 JDK、MySQL、Tomcat(图文并茂)

所需资料 下载 1.1 软件安装方式 在Linux系统中&#xff0c;安装软件的方式主要有四种&#xff0c;这四种安装方式的特点如下&#xff1a; 安装方式特点二进制发布包安装软件已经针对具体平台编译打包发布&#xff0c;只要解压&#xff0c;修改配置即可rpm安装软件已经按照re…

C#自定义控件 生成 与 加入到项目

C#自定义控件生成 在C#中&#xff0c;自定义控件通常是通过继承现有的控件类&#xff08;如UserControl、Form等&#xff09;并添加或修改其属性和方法来实现的。以下是一个简单的示例&#xff0c;演示如何创建一个自定义控件&#xff1a; 首先&#xff0c;创建一个新的Window…

sonar+gitlab提交阻断 增量扫描

通过本文&#xff0c;您将可以学习到 sonarqube、git\gitlab、shell、sonar-scanner、sonarlint 一、前言 sonarqube 是一款开源的静态代码扫描工具。 实际生产应用中&#xff0c;sonarqube 如何落地&#xff0c;需要考虑以下四个维度&#xff1a; 1、规则的来源 现在规则的…

每日一练:LeeCode-200、岛屿数量【DFS递归+BFS队列】

给你一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的的二维网格&#xff0c;请你计算网格中岛屿的数量。 岛屿总是被水包围&#xff0c;并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外&#xff0c;你可以假设该网格的四条边…

MyBatis:查询与连接池

一、查询 1、多表查询 尽量避免使用多表查询&#xff0c;尤其是对性能要求较高的项目。因为多表查询必然会导致性能变低。 例如&#xff1a;select *from ta运行需要10ms&#xff0c;select *from tb 运行也需要10s。但是&#xff0c;select *from ta left join tb on ta.xx…

python初级第一次作业

一、 dayint(input("enter today day")) fdayint(input("enter num of day since today")) c((fday%7)day)%7 if c0:print("sunday") elif c1:print("monday") elif c2:print("tuesday") elif c3:print("wendnsday&quo…

Jmeter脚本优化——CSV数据驱动文件

使用 CSV 数据文件设置实现参数化注册 1&#xff09; 本地创建 csv 文件&#xff0c;并准备要使用的数据&#xff0c;这里要参数化的是注册的用户名和邮箱。所以在 csv 文件中输入多组用户名和邮箱。 2&#xff09; 通过测试计划或者线程组的右键添加->配置元件->CSV…