知识记载:学习海康SDK的二次开发(C++)
话题
最近,学习SDK的开发和使用。但是,对SDK这一块并不熟悉,于是上网搜索资料,但是很多资料都没有讲述的很详细,甚至有很多的都是复制粘贴。同样的问题同样的回答。网上的大佬似乎觉得这个十分的简单,没有详细的说明,直接让新手去看demo示例,就连海康的开发文档都是让读者自己去看示例。(我比较笨)这个我还真不懂。弄了好久,最后还是乖乖的去看示例了。
现在看完示例并完成了制作,回来把经历写一下。放在网上提供参考一下。(注:所有的代码都是从demo示例中copy,只是加上了自己的理解,让人更加容易弄懂)
环境
实现步骤(一)
首先创建一个MFC工程,直接根据示例给出的样子设置界面(界面因为懒,没有排版,能看就行)

讯享网
然后设置配置属性,配置属性中的文件在MVS目录下,MVS目录下有个文件为Development,也就是开发者目录,里面有SDK开发所需要的东西。对于此次开发有用的东西,只有Includes、Libraries文件夹以及DLL:MvCameraControl.Net.dll,为了方便。直接将这几样东西复制到编程的目录下:

complete里面是我放的成品,也就是MVS自带的示例。只是为了方便查看,不必再去MVS目录下找它而已。不必理会,Third_Party_Platform是第一次做的时候,担心缺失环境,又冲MVS当中将其他的DLL文件考过来,而最后证明出,它也是用不到的。
附加目录,也就是刚复制过来的includes目录

附加库目录


最后加上附加依赖项,因为还需要MyCamera.h和MyCamera.cpp。这个是MVS已经自带的。不必再去修改,直接从MVS目录下复制到创建程序的目录下即可。然后在VS2010中添加即可

至此,准备工作做完。
实现步骤(二).h篇
首先打开头文件HIVsdkDlg.h,除了之前已有的代码,根据示例添加两个宏定义
#define STATUS_ERROR -1
#define IMAGE_NAME_LEN 64
然后添加每一个控件的变量。在后面的代码中需要用到
private: //打开关闭设备 CButton m_OpenSak; //在MFC添加变量,打开设备 CButton m_CloseSdk; //在MFC添加变量,关闭设备 //图像采集 CButton m_Start; //在MFC中添加变量,开始采集 CButton m_End; //在MFC中添加变量,停止采集 CButton m_single; //在MFC中添加变量,单次触发一次 CButton m_soft; //在MFC中添加变量,软触发选择 bool m_bSoftWare; //判断 //保存图片 CButton m_bmp; //在MFC中添加变量,保存为bmp图片 CButton m_jpg; //在MFC中添加变量,保存为jpg图片 //参数设置 CButton m_obtain; //在MFC中添加变量,参数获取 CButton m_set; //在MFC中添加变量,参数设置 //设置曝光、增益、帧率 double exposure_sdk; CEdit m_exposure; //在MFC中添加变量,曝光 double gain_sdk; CEdit m_gain; //在 MFC中添加变量,增益 double frame_sdk; CEdit m_frame; //在MFC中添加变量,帧率 //下拉框,IP CComboBox m_userID; int user_sdk; private: //最开始的初始化(所有的初始化) int DisplayWindow(void); //对话框初始化 int EnableSdk(BOOL blsCamera); //启动( void ShowErrorMsg(CString csMessage,int nErrorNum); //错误提示 int OpenSdk(void); //打开相机,初始化 int SetTrigger(void); //设置触发模式参数 int GetTrigger(void); //获得触发模式参数 int SetExposureTime(void); //设置曝光时间参数 int GetExposureTime(void); //获得曝光时间参数 int SetGain(void); //设置增益参数 int GetGain(void); //获得增益参数 int SetFrame(void); //设置帧率参数 int GetFrame(void); //获得帧率参数 int SetTriggerSource(void); //设置触发源参数 int GetTriggerSource(void); //获得触发源参数 int SaveImage(void); //保存图片 int CloseDevice(void); //关闭设备 private: //定义变量 //设备状态 bool m_bOpenDevice; //设备是否开启 bool m_bStartEnd; //设备是否开始抓图 int m_nTriggerMode; //触发模式选择 int m_nTriggerSource; //是否选中触发源 MV_SAVE_IAMGE_TYPE m_nSaveImageType; //保存图像格式 CMyCamera* m_pcMyCamera; // ch:CMyCamera封装了常用接口 | en:CMyCamera packed commonly used interface HWND m_hwndisplay; //显示句柄 | en:Display Handle MV_CC_DEVICE_INFO_LIST m_stDevList; // ch:设备信息列表结构体变量,用来存储设备列表 unsigned char* m_pBufForSaveImage; //用于保存图像的缓存 unsigned int m_nBufSizeForSaveImage; unsigned char* m_pBufForDriver; //用于从驱动获取图像的缓存 unsigned int m_nBufSizeForDriver;
讯享网
看起来又多又复杂。分开来理解,这儿有三处private:
第一处是控件的变量,如果对这一块不理解表示对MFC还是不太了解,需要花点时间去学习。

而像这样,换一个方向去理解瞬间觉得直观了很多。入门时添加的变量基本上都是这样添加,使用鼠标操作,直观明了。现在熟悉之后基本上是直接使用代码,会比较快。
第二处是函数。这个应该很清楚才对
第三处是程序开发中用的上的熟悉,当然这是示例中存在的例子,如果你需要额外的开发内容,可以自己添加。
在示例中没有这么详细的注释。是我对此的理解写上去的。
实现步骤(三).cpp篇
讯享网//连接相机,查找设备 void CHIVsdkDlg::OnBnClickedConnect()//连接相机,查找设备 {
CString strMsg; // ch:清除设备列表框中的信息 | en:Clear Device List Information m_userID.ResetContent(); // ch:初始化设备信息列表 | en:Device Information List Initialization memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST)); // ch:枚举子网内所有设备 | en:Enumerate all devices within subnet int nRet = CMyCamera::EnumDevices(&m_stDevList); if (MV_OK != nRet) {
return; } // ch:将值加入到信息列表框中并显示出来 | en:Add value to the information list box and display unsigned int i; int nIp1, nIp2, nIp3, nIp4; for (i = 0; i < m_stDevList.nDeviceNum; i++) {
MV_CC_DEVICE_INFO* pDeviceInfo = m_stDevList.pDeviceInfo[i]; if (NULL == pDeviceInfo) {
continue; } if (pDeviceInfo->nTLayerType == MV_GIGE_DEVICE) {
nIp1 = ((m_stDevList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24); nIp2 = ((m_stDevList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16); nIp3 = ((m_stDevList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8); nIp4 = (m_stDevList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff); wchar_t* pUserName = NULL; if (strcmp("", (LPCSTR)(pDeviceInfo->SpecialInfo.stGigEInfo.chUserDefinedName)) != 0) {
DWORD dwLenUserName = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)(pDeviceInfo->SpecialInfo.stGigEInfo.chUserDefinedName), -1, NULL, 0); pUserName = new wchar_t[dwLenUserName]; MultiByteToWideChar(CP_ACP, 0, (LPCSTR)(pDeviceInfo->SpecialInfo.stGigEInfo.chUserDefinedName), -1, pUserName, dwLenUserName); } else {
char strUserName[256] = {
0}; sprintf_s(strUserName, "%s %s (%s)", pDeviceInfo->SpecialInfo.stGigEInfo.chManufacturerName, pDeviceInfo->SpecialInfo.stGigEInfo.chModelName, pDeviceInfo->SpecialInfo.stGigEInfo.chSerialNumber); DWORD dwLenUserName = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)(strUserName), -1, NULL, 0); pUserName = new wchar_t[dwLenUserName]; MultiByteToWideChar(CP_ACP, 0, (LPCSTR)(strUserName), -1, pUserName, dwLenUserName); } strMsg.Format(_T("[%d]GigE: %s (%d.%d.%d.%d)"), i, pUserName, nIp1, nIp2, nIp3, nIp4); if (NULL != pUserName) {
delete(pUserName); pUserName = NULL; } } else if (pDeviceInfo->nTLayerType == MV_USB_DEVICE) {
wchar_t* pUserName = NULL; if (strcmp("", (char*)pDeviceInfo->SpecialInfo.stUsb3VInfo.chUserDefinedName) != 0) {
DWORD dwLenUserName = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)(pDeviceInfo->SpecialInfo.stUsb3VInfo.chUserDefinedName), -1, NULL, 0); pUserName = new wchar_t[dwLenUserName]; MultiByteToWideChar(CP_ACP, 0, (LPCSTR)(pDeviceInfo->SpecialInfo.stUsb3VInfo.chUserDefinedName), -1, pUserName, dwLenUserName); } else {
char strUserName[256]; sprintf_s(strUserName, "%s %s (%s)", pDeviceInfo->SpecialInfo.stUsb3VInfo.chManufacturerName, pDeviceInfo->SpecialInfo.stUsb3VInfo.chModelName, pDeviceInfo->SpecialInfo.stUsb3VInfo.chSerialNumber); DWORD dwLenUserName = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)(strUserName), -1, NULL, 0); pUserName = new wchar_t[dwLenUserName]; MultiByteToWideChar(CP_ACP, 0, (LPCSTR)(strUserName), -1, pUserName, dwLenUserName); } strMsg.Format(_T("[%d]UsbV3: %s"), i, pUserName); if (NULL != pUserName) {
delete(pUserName); pUserName = NULL; } } else {
ShowErrorMsg(TEXT("Unknown device enumerated"), 0);; } m_userID.AddString(strMsg); } if (0 == m_stDevList.nDeviceNum) {
ShowErrorMsg(TEXT("No device"), 0); return; } m_userID.SetCurSel(0); EnableSdk(TRUE); return; }
上面的内容完全不用在意,一大段代码全都是由示例copy出来,需要注意的只有两个地方:
m_userID
EnableSdk(TRUE);
,在原示例中是EnableControls(TRUE);这个要换成自己创建的。

EnableSdk(TRUE)的内容:
//启动设备,按钮功能,相机初始化 int CHIVsdkDlg::EnableSdk(BOOL blsCamera)//启动设备 {
GetDlgItem(IDC_OPEN)->EnableWindow(m_bOpenDevice ? FALSE : (blsCamera ? TRUE : FALSE)); GetDlgItem(IDC_CLOSE)->EnableWindow((m_bOpenDevice && blsCamera) ? TRUE : FALSE); GetDlgItem(IDC_START)->EnableWindow((m_bStartEnd && blsCamera) ? FALSE : (m_bOpenDevice ? TRUE : FALSE)); GetDlgItem(IDC_END)->EnableWindow(m_bStartEnd ? TRUE : FALSE); GetDlgItem(IDC_SOFT)->EnableWindow(m_bOpenDevice ? TRUE : FALSE); GetDlgItem(IDC_SINGLE)->EnableWindow((m_bStartEnd && m_bSoftWare)? TRUE : FALSE); GetDlgItem(IDC_BMP)->EnableWindow(m_bStartEnd ? TRUE : FALSE); GetDlgItem(IDC_JPG)->EnableWindow(m_bStartEnd ? TRUE : FALSE); GetDlgItem(IDC_EXPOSURE)->EnableWindow(m_bOpenDevice ? TRUE : FALSE); GetDlgItem(IDC_GAIN)->EnableWindow(m_bOpenDevice ? TRUE : FALSE); GetDlgItem(IDC_FRAME)->EnableWindow(m_bOpenDevice ? TRUE : FALSE); GetDlgItem(IDC_OBTAIN)->EnableWindow(m_bOpenDevice ? TRUE : FALSE); GetDlgItem(IDC_SET)->EnableWindow(m_bOpenDevice ? TRUE : FALSE); GetDlgItem(IDC_CONTINUOUS)->EnableWindow(m_bOpenDevice ? TRUE : FALSE); GetDlgItem(IDC_TRIGGER)->EnableWindow(m_bOpenDevice ? TRUE : FALSE); return MV_OK; }
这里也是,需要将IDC_换成自己创建的ID名称,以及EnableWindow后面的变量也要根据自己创建的写对。
后面的代码基本上大同小异
打开相机:
OnBnClickedOpen()
讯享网void CHIVsdkDlg::OnBnClickedOpen()//打开相机 {
// TODO: 在此添加控件通知处理程序代码 int nRet = OpenSdk(); if (MV_OK !=nRet) {
ShowErrorMsg(TEXT("Open Fail"), nRet); return; } OnBnClickedObtain(); EnableSdk(TRUE); return; }
打开相机初始化:
OpenSdk()
//打开设备 int CHIVsdkDlg::OpenSdk(void) {
if (TRUE == m_bOpenDevice)//判断相机是否开启 {
return STATUS_ERROR;//返回-1 } UpdateData(TRUE); if (TRUE==m_bOpenDevice) {
return STATUS_ERROR;//返回-1 不清楚为什么要写两个 } int nIndex = user_sdk; if (nIndex<0 | (nIndex>=MV_MAX_DEVICE_NUM)) {
ShowErrorMsg(TEXT("Plesae select device"),0); return STATUS_ERROR; } //由设备信息创建设备实例 if (NULL==m_stDevList.pDeviceInfo[nIndex]) {
ShowErrorMsg(TEXT("Device does not exist"),0); return STATUS_ERROR; } if (NULL!=m_pcMyCamera) {
return STATUS_ERROR; } m_pcMyCamera = new CMyCamera; if (NULL==m_pcMyCamera) {
return STATUS_ERROR; } int nRet = m_pcMyCamera->Open(m_stDevList.pDeviceInfo[nIndex]); if (MV_OK!=nRet) {
delete m_pcMyCamera; m_pcMyCamera = NULL; return nRet; } //探测网络**包大小 if (m_stDevList.pDeviceInfo[nIndex]->nTLayerType==MV_GIGE_DEVICE) {
int nPacketSize = m_pcMyCamera->GetOptimalPacketSize(); if (nPacketSize>0) {
nRet = m_pcMyCamera->SetIntValue("GevSCPSPacketSize",nPacketSize); if (nRet !=MV_OK) {
ShowErrorMsg(TEXT("Warning: Set Packet Size fail!"), nRet); } } else {
ShowErrorMsg(TEXT("Warning: Get Packet Size fail!"), nPacketSize); } } m_bOpenDevice = TRUE; }
开始采集
OnBnClickedStart()
讯享网//开始采集 void CHIVsdkDlg::OnBnClickedStart()//开始采集 {
// TODO: 在此添加控件通知处理程序代码 if (FALSE == m_bOpenDevice || TRUE ==m_bStartEnd) //判断当前相机是否开启,以及相机是否开始抓图 {
return ; } int nRet = MV_OK; if (NULL!=m_pcMyCamera) {
nRet = m_pcMyCamera->StartGrabbing(); if (nRet==MV_OK) {
nRet = m_pcMyCamera->Display(m_hwndisplay); } } else {
return; } if (MV_OK !=nRet) {
return; } m_bStartEnd = TRUE; EnableSdk(TRUE); return; }
测试

写完之后就可以简单的进行图像采集了。剩下的控件功能可以根据示例当中的写。
再次注释:
很多代码相似是因为是直接copy示例当中的,只是改了些控件名称而已,该篇仅供参考。与原本的示例相比,只是多了些自己理解的代码。
写下来是为了巩固自己。如果能够帮助初学者那么更加的好。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/128858.html