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

news/2024/4/23 21:03:56/

系列文章目录

提示:这里是该系列文章的所有文章的目录
第一章: (一)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.ppmy.cn/news/1395898.html

相关文章

SpringBoot集成Solr全文检索

SrpingBoot 集成 Solr 实现全文检索 一、核心路线 使用 Docker 镜像部署 Solr 8.11.3 版本服务使用 ik 分词器用于处理中文分词使用 spring-boot-starter-data-solr 实现增删改查配置用户名密码认证使用 poi 和 pdfbox 组件进行文本内容读取文章最上方有源码和 ik 分词器资源…

Day75:WEB攻防-验证码安全篇接口滥用识别插件复用绕过宏命令填入滑块类

目录 图片验证码-识别插件-登录爆破&接口枚举 登录爆破 接口枚举 图片验证码-重复使用-某APP短信接口滥用 滑块验证码-宏命令-某Token&Sign&滑块案例 知识点&#xff1a; 1、验证码简单机制-验证码过于简单可爆破 2、验证码重复使用-验证码验证机制可绕过 3、…

带你学会深度学习之循环神经网络[RNN] - 3

前言 笔者写下此系列文章是希望在复习人工智能相关知识同时为想学此技术的人提供一定帮助。 图源网络&#xff0c;所有者可随时联系笔者删除。 代码不代表全部实现&#xff0c;只是为展示模型的关键结构。 与CNN不同&#xff0c;RNN被设计用来处理序列数据。它通过在网络的…

Java | 1000以内的完数查找

大家可以关注一下专栏&#xff0c;方便大家需要的时候直接查找&#xff0c;专栏将持续更新~ 题目描述 编写一个Java程序&#xff0c;用于找出1000以内的所有完数。一个完数是指它的因子&#xff08;除了自身以外的约数&#xff09;之和等于它本身的数。例如&#xff0c;6是一…

Python Flask框架 -- flask-migrate迁移ORM模型

# 之前使用的这个db.create_all()很有局限性&#xff0c;它不能把在class里修改的东西同步上数据库&#xff0c;所以不用了 # with app.app_context(): # 请求应用上下文 # db.create_all() # 把所有的表同步到数据库中去 例如&#xff0c;在User类中增加一个email字段&…

Javascript中的严格模式 “use strict“

一、为什么使用严格模式&#xff1f; 在普通的 JavaScript 中&#xff0c;写错变量名会创建新的全局变量&#xff0c; 在严格模式中&#xff0c;写错变量名会抛出错误来提醒开发者 二、声明严格模式 通过在脚本或函数的开头添加 “use strict”; 来声明严格模式。"use …

道可云元宇宙每日资讯|国家能源局:探索推广虚拟电厂等新技术

道可云元宇宙每日简报&#xff08;2024年3月25日&#xff09;讯&#xff0c;今日元宇宙新鲜事有&#xff1a; 国家能源局&#xff1a;探索推广虚拟电厂等新技术 国家能源局印发《2024年能源工作指导意见》&#xff0c;其中提出&#xff0c;促进能源新技术应用示范。组织开展能…

基于BP神经网络的城市空气质量数据预测matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 BP神经网络结构 4.2 神经元模型与激活函数 4.3 前向传播过程 4.4反向传播算法及其误差函数 4.5 权重更新规则 4.6 迭代训练 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软…

深入探索C++对象模型(二)

类对象占用的空间 #include "pch.h" #include <iostream> using namespace std;class A {public: };//类对象所占用的空间 int main() {//std::cout << "Hello World!\n"; A obja;int ilen = sizeof(obja); cout << ilen << endl…

Linux线程补充——周边问题

一、线程池 ​ 使用多线程时要注意传参传递堆空间指针变量&#xff1b; ​ 平常定义的缓冲区就是一个简单的数据池&#xff1b;malloc的底层调用了系统调用来申请堆空间是有成本的&#xff0c;如&#xff1a;需要使用页表和MMU将虚拟地址和物理地址建立映射&#xff0c;期间会…

python、execl数据分析(数据描述)

一 python 1.各函数 1.1python库的安装与导入 #pip install os#pip install matplotlib#pip install seaborn#pip install scikit-learn#pip install scipy#修 改 工 作 目 录import osos.getcwd () # 查看当前工作环境os.chdir( F :\my course\database ) # 修改工作环境o…

RT Studio 仍存在的一些bug

年前有参加RT官方组织的活动&#xff0c;本来觉得是一路next的使用体验所以就没有提前跑一遍&#xff0c;然后现场做实验的时候&#xff0c;尴尬了。 安装官方guide&#xff0c;下载工具链&#xff0c;下载bsp&#xff0c;新建开发板项目&#xff0c;下载软件组件&#xff0c;全…

树梅派Raspberry Pi OS(Debian)源码交叉编译升级内核参数PAGESIZE

树梅派Raspberry Pi OS(Debian)源码交叉编译升级内核参数PAGESIZE 环境&#xff1a; device: Raspberry Pi 3 Model B Rev 1.2 os: 2024-03-15-raspios-bookworm-arm64 (Debian GNU/Linux 12 bookworm aarch64) kernel: 6.6.20rpt-rpi-v8 arch: aarch64 编译机: ubuntu 22.0…

Ubuntu20.04下VSCode配置PCL和OpenCV库-C++

Ubuntu20.04 VSCode Cpp PCL OpenCV 准备工作 代码编辑&#xff1a;VSCode 开发语言&#xff1a;C 编译工具&#xff1a;Cmake G 依赖需求&#xff1a;PCL / OpenCV 安装PCL库 sudo apt install libpcl-dev配置OpenCV库 安装依赖 sudo apt-get install build-essenti…

C++关于类和对象的基础语法

前言&#xff1a; 介绍c中类和对象的基础语法和注意事项&#xff0c;这里是c入门的第一道坎&#xff0c;细节很多&#xff0c;在后面的更深的学习中还会反复提到。 目录 前言&#xff1a; 1.OO语言 2.类的定义 3.类的访问限定符与封装的引入 4.类的实例化 5.关键字this指…

反相器的工艺结构原理及选型参数总结

🏡《总目录》 目录 1,概述2,工作原理3,结构特点3.1,输入与输出电平相反3.2,增益小于13.3,输入阻抗高,输出阻抗低4,工艺流程4.1,硅晶圆准备4.2,电路设计4.3,光刻图形定义4.4,离子注入4.5,沉积4.6

【代码片】图像处理工具OpenCV、JAI、ImageJ、Thumbnailator和Graphics2D

Graphics2D图像压缩 import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File;public class ImageResolutionModifier {public static void main(String[] args) {// 输入图片路径和输出图片路径String inputImagePath …

apisix创建https

总结了下apisix 使用https 的问题和方法 1、apisix 默认https 端口是9443 2、apisix 需要上传证书后才可以使用https 否二curl测试会报错 SSL routines:CONNECT_CR_SRVR_HELLO 3、apisix 上传证书方法 我是使用的自签名证书&#xff0c;注意自签名证书的Common Name 要写你…

前端删除列表数据后页码重置逻辑

问题描述 需要调整页码的例子&#xff1a; 列表一共有10页数据&#xff0c;用户把第10页数据全部删除后&#xff0c;需要把数据重置成上一页&#xff0c;也就是第9页 不用调整页码的例子&#xff1a; 列表一共有1页数据&#xff0c;用户把本页数据全部删除后&#xff0c;页码…

【前端面试3+1】01闭包、跨域

一、对闭包的理解 定义&#xff1a; 闭包是指在一个函数内部定义的函数&#xff0c;并且该内部函数可以访问外部函数的变量。闭包使得函数内部的变量在函数执行完后仍然可以被访问和操作。 特点&#xff1a; 闭包可以访问外部函数的变量&#xff0c;即使外部函数已经执行完毕。…