修改日期:2021-11–19
问题状态:已解决
当前电脑:10400F+1660S
负责人:张阳
当前环境:Ubuntu20.04
使用设备:MindVision工业相机*2
编译器:g++9.3.0
问题描述:
用 C++ 调用两个工业相机时出现错误,无法同时调用。

问题分析:
根据报错查看错误代码代表含义,在 CameraStatus.h 文件中查到 -18 报错的宏定义:
CAMERA_STATUS_DEVICE_IS_OPENED
意思是设备已经打开,也就是说在检测到一个相机已经打开后程序就不再检测设备列表中是否还有第二个可用相机存在。
也就是说要让程序知道设备列表中还有第二个相机,或者让他知道我在外面两次定义的不同 VedioCapture 变量想要初始化的不是同一个相机。
解决方案:
1.先找到相机初始化最核心的代码:
iStatus = CameraInit(&tCameraEnumList,-1,-1,&hCamera);
查找函数定义:

发现 &tCameraEnumList 与 &hCamera 都是指针型变量,且注释定义中对 &hCamera(即pCameraHandle )有这样一句话:相机的句柄指针,初始化成功后,该指针返回相机的有效句柄,在调用其他相机相关的操作接口时,都需要传入该句柄,主要用于多相机之间的区分。
我们的需求是双相机调用,而这两个是指针变量,那就意味着其实我们可以传入一个数组,大小可存放两个相机的设备号,即 2 。
2.修改关键变量定义
去找代码中这 &tCameraEnumList 和 &hCamera 的定义,看看原来定义了什么。
tCameraEnumList:

hCamera( iCameraCounts 也是后面改的,原来是没有定义为 2 的,之前忘记了):

按照思路我们将 tCameraEnumList 改为 tCameraEnumList[2] ,将 hCamera 直接赋值 2 。
3.分别测试两个相机,找他的设备序列号
经过反复拔插测试之后,发现这两个相机的序列号不是 0 就是 1 ,也就是说只要我外部指定好 0 或者 1 传进去,让他知道 0 也行 1 也行就可以了。
但是因为 CameraInit 的第一个参数他只能传入 tSdkCameraDevInfo 类型,不能传入整形数据(不能直接赋值 0 或 1 ),我们又要区分开两个相机,所以初始化相机的核心代码改成这样:

// 相机初始化
if(_CAMERA_INDEX==0)
{
iStatus = CameraInit(&tCameraEnumList[0], -1, -1, &hCamera);
}else
{
iStatus = CameraInit(&tCameraEnumList[1], -1, -1, &hCamera);
}
_CAMERA_INDEX 用于我们外部人工指定序列号,当它被指定为 0 时,代表初始化 0 号相机,如果被指定成 1(其他数字都不行),代表初始化 1 号相机。
( 2021-12-6 ) MindVision 的驱动总共有 3 个相机初始化 API ,上面是其中的一个,另外两个同样也可以用,这是第二个:

初始化核心代码:
if(_CAMERA_INDEX==0)
{
iStatus = CameraInitEx(0, -1, -1, &hCamera);
}
else
{
iStatus = CameraInitEx(1, -1, -1, &hCamera);
}
CameraEnumerateDeviceEx() 返回相机个数:
int index_num=CameraEnumerateDeviceEx();
第三种方法是根据相机昵称来初始化:
相机昵称在 tSdkCameraDevInfo.acFriendlyName 中 ( tSdkCameraDevInfo[0].acFriendlyName )

这个相机昵称可以自己设置,用 CameraSetFriendlyName 函数即可:
该函数在 CameraApi.h 文件中.

使用,昵称自定,在相机初始化( 可以先将原本的昵称输出出来看看 )的时候重新设置就好,设置完后将此函数去掉就行,在这里为了方便就将初始化方法和昵称设置方法都写在这了:
if(_CAMERA_INDEX==0)
{
iStatus = CameraInitEx2("radar_video_0", &hCamera);
CameraSetFriendlyName(hCamera,"radar_video_0");
std::cout<<"acFriendlyName[0]:"<<tCameraEnumList[0].acFriendlyName<<std::endl;
}
else
{
iStatus = CameraInitEx2("radar_video_1", &hCamera);
CameraSetFriendlyName(hCamera,"radar_video_1");
std::cout<<"acFriendlyName[1]:" <<tCameraEnumList[1].acFriendlyName<<std::endl;
}
4.由此一直从里往外改
修改初始化定义:

增加参数:

修改 cameraInit 在类中的声明:

修改 VedioCapture 的构造函数:

最后修改主函数中的定义:

实验测试:
调用成功
