工业相机如何调整SDK枚举顺序或者打开顺序
工业相机如何调整SDK枚举顺序或者打开顺序

工业相机如何调整SDK枚举顺序或者打开顺序

当使用海康工业相机SDK时,调用其枚举接口然后打开相机时,会有出现一个问题,打开顺序是固定的,如果更换相机,相机的顺序又会出现变化,总结下规律,可以发现,其顺序是根据相机出厂序列号从小到大来的
但是,对于使用者来讲,还是会有个很尴尬的问题,多相机,在设备安装时,肯定不可能严格按照序列号大小依次安装,总会出现乱序的情况,那么怎样才能顺风顺水的打开我想要的相机呢
0dedb814bbf9963e118885c72d28bdc2.png

1.方法1:针对枚举出来的顺序重新排序

SDK调用的第一步,通常是枚举相机,那么枚举出来的信息,都在相机结构体 MV_CC_DEVICE_INFO_LIST 里面,我们通过去改变结构体里面的排序,自然就可以改变打开顺序设备信息结构体

/// \~chinese 设备信息列表              \~english Device Information List
typedef struct _MV_CC_DEVICE_INFO_LIST_
{
    unsigned int        nDeviceNum;                                 ///< [OUT] \~chinese 在线设备数量           \~english Online Device Number
    MV_CC_DEVICE_INFO*  pDeviceInfo[MV_MAX_DEVICE_NUM];             ///< [OUT] \~chinese 支持最多256个设备      \~english Support up to 256 devices
}MV_CC_DEVICE_INFO_LIST;
/// \~chinese 设备信息                  \~english Device info
typedef struct _MV_CC_DEVICE_INFO_
{
    unsigned short          nMajorVer;                              ///< [OUT] \~chinese 主要版本               \~english Major Version
    unsigned short          nMinorVer;                              ///< [OUT] \~chinese 次要版本               \~english Minor Version
    unsigned int            nMacAddrHigh;                           ///< [OUT] \~chinese 高MAC地址              \~english High MAC Address
    unsigned int            nMacAddrLow;                            ///< [OUT] \~chinese 低MAC地址              \~english Low MAC Address
    unsigned int            nTLayerType;                            ///< [OUT] \~chinese 设备传输层协议类型     \~english Device Transport Layer Protocol Type

    unsigned int            nReserved[4];                           ///<       \~chinese 预留                   \~english Reserved

    union
    {
        MV_GIGE_DEVICE_INFO stGigEInfo;                             ///< [OUT] \~chinese GigE设备信息           \~english GigE Device Info
        MV_USB3_DEVICE_INFO stUsb3VInfo;                            ///< [OUT] \~chinese USB设备信息            \~english USB Device Info
        MV_CamL_DEV_INFO    stCamLInfo;                             ///< [OUT] \~chinese CameraLink设备信息     \~english CameraLink Device Info
        // more ...
    }SpecialInfo;

}MV_CC_DEVICE_INFO;
/// \~chinese GigE设备信息              \~english GigE device info
typedef struct _MV_GIGE_DEVICE_INFO_
{
    unsigned int        nIpCfgOption;                               ///< [OUT] \~chinese IP配置选项             \~english IP Configuration Options
    unsigned int        nIpCfgCurrent;                              ///< [OUT] \~chinese 当前IP配置             \~english IP Configuration:bit31-static bit30-dhcp bit29-lla
    unsigned int        nCurrentIp;                                 ///< [OUT] \~chinese 当前IP地址             \~english Current Ip
    unsigned int        nCurrentSubNetMask;                         ///< [OUT] \~chinese 当前子网掩码           \~english Curtent Subnet Mask
    unsigned int        nDefultGateWay;                             ///< [OUT] \~chinese 当前网关               \~english Current Gateway
    unsigned char       chManufacturerName[32];                     ///< [OUT] \~chinese 制造商名称             \~english Manufacturer Name
    unsigned char       chModelName[32];                            ///< [OUT] \~chinese 型号名称               \~english Model Name
    unsigned char       chDeviceVersion[32];                        ///< [OUT] \~chinese 设备版本               \~english Device Version 
    unsigned char       chManufacturerSpecificInfo[48];             ///< [OUT] \~chinese 制造商的具体信息       \~english Manufacturer Specific Information
    unsigned char       chSerialNumber[16];                         ///< [OUT] \~chinese 序列号                 \~english Serial Number
    unsigned char       chUserDefinedName[16];                      ///< [OUT] \~chinese 用户自定义名称         \~english User Defined Name 
    unsigned int        nNetExport;                                 ///< [OUT] \~chinese 网口IP地址             \~english NetWork IP Address
    unsigned int        nReserved[4];                               ///<       \~chinese 预留                   \~english Reserved
}MV_GIGE_DEVICE_INFO;

实现方法:
第一步:枚举相机信息:

 // ch:枚举设备 | Enum device
        MV_CC_DEVICE_INFO_LIST stDeviceList;
        memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
        nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList);
        if (MV_OK != nRet)
        {
            printf("Enum Devices fail! nRet [0x%x]\n", nRet);
            break;
        }

第二步:根据相机IP大小,从小到大重新排序(如果想根据其他信息排序,if的判断语句就应该做对应修改,例如,改成chUserDefinedName、序列号等)

for (int i = 0; i < psDevlist->nDeviceNum; i++)
{
	for (int j = 0; j < psDevlist->nDeviceNum-i-1; j++)
	{
	//USB相机,SpecialInfo.stGigEInfo就需要变成SpecialInfo.stUSBInfo,换成其他设备信息来排序
		if(psDevlist->pDeviceInfo[j]->SpecialInfo.stGigEInfo.nCurrentIp > psDevlist->pDeviceInfo[j+1]->SpecialInfo.stGigEInfo.nCurrentIp)
		{
			MV_CC_DEVICE_INFO* temp = psDevlist->pDeviceInfo[j];
			psDevlist->pDeviceInfo[j]=psDevlist->pDeviceInfo[j+1];
			psDevlist->pDeviceInfo[j+1]=temp;
		}
	}
}

第三步:正常打开就行

完整代码如下:

//------------------根据ip大小修改默认排序-----------------------
int EnumDeviceBycuirentIp(IN unsigned int nTLayerType,IN OUT MV_CC_DEVICE_INFO_LIST*psDevlist)
{
	int nRet = MV_CC_EnumDevices(nTLayerType,psDevlist);
	if (MV_OK != nRet)
	{
		printf("Enum Devices fail! nRet [0x%x]\n", nRet);
		return nRet;
	}
	for (int i = 0; i < psDevlist->nDeviceNum; i++)
	{
		for (int j = 0; j < psDevlist->nDeviceNum-i-1; j++)
		{
			if(psDevlist->pDeviceInfo[j]->SpecialInfo.stGigEInfo.nCurrentIp > psDevlist->pDeviceInfo[j+1]->SpecialInfo.stGigEInfo.nCurrentIp)
			{
				MV_CC_DEVICE_INFO* temp = psDevlist->pDeviceInfo[j];
				psDevlist->pDeviceInfo[j]=psDevlist->pDeviceInfo[j+1];
				psDevlist->pDeviceInfo[j+1]=temp;
			}
		}
	}
	return nRet;
}
//-------------------主函数部分----------------------------------
	// ch:枚举设备 | en:Enum device
		MV_CC_DEVICE_INFO_LIST stDeviceList;
		memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
		unsigned int nTLayerType=MV_GIGE_DEVICE;
		MV_CC_DEVICE_INFO_LIST *psDevlist;
		nRet = EnumDeviceBycuirentIp(nTLayerType,&stDeviceList);
		if (MV_OK != nRet)
		{
			printf("Enum Devices fail! nRet [0x%x]\n", nRet);
			return nRet;
		}
		if (stDeviceList.nDeviceNum > 0)
		{
			for (unsigned int i = 0; i < stDeviceList.nDeviceNum; i++)
			{
				printf("[device %d]:\n", i);
				MV_CC_DEVICE_INFO* pDeviceInfo = stDeviceList.pDeviceInfo[i];
				if (NULL == pDeviceInfo)
				{
					break;
				} 
				PrintDeviceInfo(pDeviceInfo);            
			}  
		} 
		else
		{
			printf("Find No Devices!\n");
			break;
		}

2.方法2:根据相机序列号或自定义名称指定打开相机

前面讲了,我们可以根据相机信息结构体中设备信息,重新修改排序,那么应该可以做一个简单的循环,比对信息来打开我指定的相机,如下,指定打开一个命名叫“CCDName”的相机

bcd8803bbff193f8af384ad4dc0e3029.png
实现方法:

	int nRet = 0;
	char* ccdName={"CCDName"};
	int nDeviceNum = -1;
	unsigned int VersionSDK = MV_CC_GetSDKVersion();
	MV_CC_DEVICE_INFO_LIST stDeviceList;
	memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
	nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList);
	if (MV_OK != nRet)
	{
		printf("MV_CC_EnumDevices fail! nRet %x\n", nRet);
		return nRet;
	}
	if (stDeviceList.nDeviceNum < 0)
	{
		return -1;
	}
	for (unsigned int i = 0; i < stDeviceList.nDeviceNum; i++)
	{
		if (stDeviceList.pDeviceInfo[i]->nTLayerType == MV_GIGE_DEVICE)
		{
			if (strcmp((const char*)stDeviceList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.chUserDefinedName, ccdName)==0)
			{
				nDeviceNum = i;
				printf("Gige_devicen_nDeviceNum %d\n", nDeviceNum);
			}
		}
		else if (stDeviceList.pDeviceInfo[i]->nTLayerType == MV_USB_DEVICE)
		{
			if (strcmp((const char*)stDeviceList.pDeviceInfo[i]->SpecialInfo.stUsb3VInfo.chUserDefinedName, ccdName)==0)
			{
				nDeviceNum = i;
				printf("USB_devicen_DeviceNum %d\n", nDeviceNum);
			}
		}
		continue;
	}
	if (nDeviceNum < 0)
	{
		return -1;
	}
	nRet = MV_CC_CreateHandle(&handle, stDeviceList.pDeviceInfo[nDeviceNum]);
	if (MV_OK != nRet)
	{
		printf("Camera;%s->MV_CC_CreateHandle fail! nRet %x\n", ccdName, nRet);
		return nRet;
	}
	nRet = MV_CC_OpenDevice(handle);
	if (MV_OK != nRet)
	{
		printf("Camera;%s->MV_CC_OpenDevice fail! nRet %x\n",ccdName,nRet);
		return nRet;
	}

3.方法3:根据指定的ip地址,打开固定ip的相机

既然我们对相机信息结构体有了一定了解,那么为啥不能自己向里面填充信息呢
下面的代码就是自己填写ip地址,打开固定ip地址的相机,用这种方法呢,可以跳过枚举接口,直接获取信息创建句柄

//指定网卡ip,相机ip打开相机,需注意,不要写错ip地址,否则会报错206问题
	int nRet = 0;
	int nDeviceNum = -1;
	MV_CC_DEVICE_INFO stDevInfo = { 0 };
	MV_GIGE_DEVICE_INFO stGigEDev = { 0 };
	stGigEDev.nNetExport = 0x0a403951;//网卡ip地址 10.64.57.81
	stGigEDev.nCurrentIp = 0x0a40395b;//相机ip地址 10.64.57.91
	stDevInfo.nTLayerType = MV_GIGE_DEVICE;// ch:仅支持GigE相机 | en:Only support GigE camera
	stDevInfo.SpecialInfo.stGigEInfo = stGigEDev;
	nRet = MV_CC_CreateHandle(&handle, &stDevInfo);
	if (MV_OK != nRet)
	{
		printf("MV_CC_CreateHandle fail! nRet [%x]\n", nRet);
		return -1;
	}
	nRet = MV_CC_GetDeviceInfo(handle, &stDevInfo);//补全设备信息
	if (nRet != MV_OK)
	{
		MV_CC_DestroyHandle(handle);
		handle = NULL;
		return false;
	}
	nRet = MV_CC_OpenDevice(handle);
	if (MV_OK != nRet)
	{
		printf("MV_CC_OpenDevice fail! nRet %x\n",  nRet);
		return nRet;
	}

以上三种方法,实测可行,如果有更多的方法与思路,可以评论交流

版权声明:本文为V社区用户原创内容,转载时必须标注文章的来源(V社区),文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:v-club@hikrobotics.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
上一篇

海康机器人工业相机sdk简介

下一篇

Opencv如何打开使用海康工业相机

评论请先登录 登录
全部评论 0
Lv.0
0
关注
0
粉丝
0
创作
0
获赞
相关阅读
  • 3D激光轮廓仪对射拼接详解
    2025-09-01 浏览 0
  • 案例征集
    2025-09-17 浏览 0
  • 汇川iFA软件功能分析
    2025-09-03 浏览 0
  • VM通信常见应用方式
    2025-09-19 浏览 0

请升级浏览器版本

您正在使用的浏览器版本过低,请升级最新版本以获得更好的体验。

推荐使用以下浏览器