需求

项目要求一个后台服务,通过交换机连接并监控多个Basler相机,项目的细节点就在于实时监控配置列表中所有的相机(相机未在线等待事件,相机断连事件,相机参数初始化,相机拍照结果返回获取等)

连接相机

当安装Basler相机驱动时选择Developer安装则可以在安装目录下发现现成的demo,如下图
这里我们用C#开发,根据demo可以知道basler开发所引用的底层库有两种PylonC.Net.dll & Basler.Pylon.dll, 项目里我引用的是 PylonC.Net.dll(我测试发现PylonC要稳定些),确保所有相机和电脑都在同一局域网且网段相同。
下面是简单的调用和连接相机:

using PylonC.Net;
public void OpenCamera()
{Pylon.Initialize();//初始化uint deviceNums = Pylon.EnumerateDevices();//获取当前所有可连接相机数for(int i=0; i<=deviceNums -1; i++){PYLON_DEVICE_HANDLE hDev = Pylon.CreateDeviceByIndex(i);PYLON_DEVICE_INFO_HANDLE deviceInfo = Pylon.GetDeviceInfoHandle(i);Pylon.DeviceOpen(hDev, Pylon.cPylonAccessModeControl | Pylon.cPylonAccessModeStream);//打开相机,并设定连接模式}
}

采图及参数设置

相机已经打开了那就获取照片:

private void SaveImage(PYLON_DEVICE_HANDLE hDev)
{PylonBuffer<Byte> imgBuf = null;  //图像缓存PylonGrabResult_t grabResult; //图像结果返回if(Pylon.DeviceFeatureIsAvailable(hDev,"EnumEntry_PixelFormat_Mono8")) //检查相机设备是否支持该像素Mono8设置{Pylon.DeviceFeatureFromString(hDev,"PixelFormat","Mono8"); //设置像素格式}if(Pylon.DeviceFeatureIsAvailable(hDev, "EnumEntry_TriggerSelector_FrameStart")) {Pylon.DeviceFeatureFromString(hDev, "TriggerSelector", "FrameStart");Pylon.DeviceFeatureFromString(hDev, "TriggerMode", "Off");  //设置触发模式,off就是关闭触发模式}if(Pylon.DeviceFeatureIsWritable(hDev, "GevSCPSPacketSize")){Pylon.DeviceSetIntegerFeature(hDev, "GevSCPSPacketSize", 1500); //设置数据传输包的大小}if(!Pylon.DeviceGrabSingleFrame(hDev, 0, ref imgBuf, out grabResult, 500)){/*图片采集时间超出*/}if(grabResult.Status == EPylonGrabStatus.Grabbed)//图片已经采集{Pylon.ImageWindowDisplayImage<Byte>(0, imgBuf, grabResult);//显示图片}}

像上面那段代码关于相机参数的设置还有很多项,从相机驱动的设置界面就可以感受到。在实际项目中,对应这样的设置后端一般都是使用配置文件,把需要配置的参数根据需求维护上,在循环设置就好。
配置

<?xml version="1.0"?>
<ArrayOfCameraSetData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CameraSetData>  <MAC>003053285C3C</MAC><SNO>01</SNO><TimeOut>180000</TimeOut><CameraParams><CameraParam><IsAvailMethod>DeviceFeatureIsAvailable</IsAvailMethod><SetValueMethod>DeviceFeatureFromString</SetValueMethod><FeatureName>EnumEntry_PixelFormat_Mono8</FeatureName><Name>PixelFormat</Name><Value>Mono8</Value></CameraParam>      <CameraParam><IsAvailMethod>DeviceFeatureIsAvailable</IsAvailMethod><SetValueMethod>DeviceFeatureFromString</SetValueMethod><FeatureName>EnumEntry_TriggerSelector_FrameStart</FeatureName><Name>TriggerSelector</Name><Value>FrameStart</Value></CameraParam></CameraParams></CameraSetData></ArrayOfCameraSetData>

上面的配置主要就是针对多相机情况下的设置,需要维护对应相机Mac地址以及固定编号,参数维护只写了两个。
关于xml的解析直接XML序列化,当然需要对应的实体:

    /// <summary>/// 相机参数类/// </summary>[Serializable]public class CameraSetData{public string MAC { get; set; }public string SNO { get; set; }public uint TimeOut { get; set; }public List<CameraParam> CameraParams { get; set; }}[Serializable]public class CameraParam{/// <summary>/// 判断方法是否可用/// </summary>public string IsAvailMethod { get; set; }/// <summary>/// 相机参数值设置方法/// </summary>public string SetValueMethod { get; set; }public string FeatureName { get; set; }public string Name { get; set; }public string Value { get; set; }}

序列化以及参数配置写法

using (FileStream fs = new FileStream(CacheHelper.cameraSettingPath, FileMode.Open, FileAccess.Read))
{XmlSerializer xml = new XmlSerializer(typeof(List<CameraSetData>));listSetData = (List<CameraSetData>)xml.Deserialize(fs);
}
for(int i = 0; i < Pylon.EnumerateDevices();i++)
{PYLON_DEVICE_INFO_HANDLE deviceInfo = Pylon.GetDeviceInfoHandle(i);//取对应编号的相机信息PYLON_DEVICE_HANDLE hDev = Pylon.CreateDeviceByIndex(i);String mac = Pylon.DeviceInfoGetPropeertyValueByName( deviceInfo, Pylon.cPylonDeviceInfoMacAddressKey);CameraSetData setData = listSetData.Where(a => a.Mac == mac).FirstOrDefault();if(setData !=null){if (!Pylon.DeviceIsOpen(hDev))Pylon.DeviceOpen(hDev, Pylon.cPylonAccessModeControl | Pylon.cPylonAccessModeStream);List<CameraParam> listParam = setData.CameraParams;for(int j = 0; j < listParam.Count; j++){isAvail = Pylon.DeviceFeatureIsAvailable(hDev, listParam[j].FeatureName);if(isAvail){Pylon.DeviceFeatureFromString(hDev, listParam[j].Name, listParam[j].Value);}}}
}

上面的是简写,实际情况还要区分一些属性判断,因为属性也分在大类里。
然后要讲下我在实际项目中遇到的一个坑,这个坑就是参数没有设置好的原因
就如下图,图片返回始终丢帧,也就是在程序实际采集中一直无法正确的grabbed,最后用驱动一直慢慢调慢慢调才找到是因为pacekt size 和delpoy参数没有设置好。因为数据传输层是走网卡的,当多个相机同时连接在一个交换机的时候它们的包参数就要适当的修改下,而且对应于不同的交互机不同的网卡参数往往还不一样。

多相机连接监控及重连机制

当按照设定的配置文件需要连接多个相机时,可以启一个连接检查线程,用来检测还未连接上的相机。如果一直有相机未连接上那么这个线程就随程序一直运行着直到这个相机上线为止。(不过没有写线程守护机制哈)配置检测都是用相机的Mac地址。

static List<CameraSetData> listSetData = new List<CameraSetData>();
static List<PYLONDEVICE> listDevices = new List<PYLONDEVICE>();
public static void OpenCamera()
{lock(objLock){listSetData.Clear();//所配置相机集合listDevices.Clear();//所检测到的相机集合}//获取配置相机集合using (FileStream fs = new FileStream(CacheHelper.cameraSettingPath, FileMode.Open, FileAccess.Read)){XmlSerializer xml = new XmlSerializer(typeof(List<CameraSetData>));listSetData = (List<CameraSetData>)xml.Deserialize(fs);}Pylon.Initialize();//驱动初始化int numDevices = Pylon.EnumerateDevices(); //获取当前网域下相机连接数if(numDevices != listSetData.Count){Thread.Sleep(10000);numDevices = Pylon.EnumerateDevices();}for (uint i = 0; i < numDevices; i++){PYLON_DEVICE_HANDLE hDev = Pylon.CreateDeviceByIndex(i);PYLON_DEVICE_INFO_HANDLE deviceInfo = Pylon.GetDeviceInfoHandle(i);SetCameraSetting(hDev, deviceInfo, true);//这个方法就是细节处理相机,比如上面写的参数设置等}if(listDevices.Count < listSetData.Count){Thread tCheck = new Thread(() =>{CheckCameras();});tCheck.IsBackground = true;tCheck.Start();}
}private static void CheckCameras()
{PYLON_DEVICE_INFO_HANDLE deviceInfo = null;string mac = string.Empty;PYLON_DEVICE_HANDLE hDev = null;PYLONDEVICE deviceTemp = null;unint num;while(true){try{      num = Pylon.EnumerateDevices();for(uint i = 0;i<num;i++){deviceinfo = Pylon.GetDeviceInfoHandle(i);mac = Pylon.DeviceInfoGetPropertyValueByName(deviceInfo,Pylon.cPylonDeviceInfoMacAddressKey);hDev = Pylon.CreateDeviceByIndex(i);// 创建设备deviceTemp = listDevices.Where(a => a.MAC == mac).FirstOrDefault();if(deviceTemp == null){SetCameraSetting(hDev,deviceInfo,true);}            }if(num == listSetData.Count)break;//检测到的相机都在线了           }catch(Exception){}finally{deviceInfo = null;mac = string.EmptyhDev = null;deviceTemp = null;GC.Collect();}Thread.Sleep(1000);}
}

下面这个方法就是SetCameraSetting 里面添加了断线重连机制

private static void SetCameraSetting(PYLON_DEVICE_HANDLE hDev, PYLON_DEVICE_INFO_HANDLE deviceInfo, bool isAdd)
{String mac = Pylon.DeviceInfoGetPropertyValueByName(deviceInfo, Pylon.cPylonDeviceInfoMacAddressKey);CameraSetData setData = listSetData.Where(a => a.MAC == mac).FirstOrDefault();if (setData != null){lock (objLock){listDevices.Add(device);}DeviceCallbackHandler cb = new DeviceCallbackHandler();//重连操作cb.CallbackEvent += cb_CallbackEvent;//注册重连事件Pylon.DeviceRegisterRemovalCallback(hDev, cb);//重连注册的回调}//这里还应该开个线程去采图,也就是每个相机事件都要开个采图线程去监听有没有图片返回
}static void cb_CallbackEvent(PYLON_DEVICE_HANDLE hDev)
{Pylon.DeviceClose(hDev);Pylon.DestroyDevice(hDev);PYLONDEVICE devTemp = listDevices.Where(a => a.Device == hDev).FirstOrDefault();if (devTemp != null){lock (objLock){listDevices.Remove(devTemp);}}//再次开启检测线程Thread tCheck = new Thread(() =>{CheckCameras();});tCheck.IsBackground = true;tCheck.Start();
}

上面这部分只是相机业务,实际项目中可能会综合整个框架去着手,例如状态监控,例如上位操作等等。。。以后有机会了说下。
代码上传地址:多个Basler相机连接测试

项目总结之Basler相机的调用相关推荐

  1. Basler相机调用及图像存储

    使用方式SDK,工程直接引用Basler.Pylon.dll 调用步骤: //实例化相机 Camera camera = new Camera(); //打开相机 camera.Open(); //开 ...

  2. basler相机pylon安装及API调用

    1.官网下载basler相机的pylon 2.安装pylon 2.1选择pylon的模式,二次开发选择development模式 2.2选择接口,看相机的接口类型,选择相机的接口类型一般为GitE和U ...

  3. VS(C#)调用Basler相机SDK采集图像及基本功能设定

    注意一定要安装那个 巴斯勒的程序后在运行代码 ,要不然就报什么组建错误 注:博主看着另外一个博主的博客才有下面的一些总结,有兴趣可以看一下:https://blog.csdn.net/qq_39930 ...

  4. Qt(C++)项目中使用 Basler 工业相机(2 参数设置)

    Qt(C++)项目中使用 Basler 工业相机(2 参数设置) 上一篇博客介绍了 pylon 的基本结构和如何枚举系统中的相机.这一篇主要讲讲如何设置相机的各个参数. 在设置相机参数之前,先要获取相 ...

  5. Qt(C++)项目中使用 Basler 工业相机(图像获取策略)

    Qt(C++)项目中使用 Basler 工业相机(图像获取策略) Pylon 中的 CInstantCamera 类支持四种图像获取策略,分别称为: One by One Grab Strategy ...

  6. android相机采集sdk,C#用basler相机sdk采集图像并用halcon显示的小程序

    C#用basler相机sdk采集图像并用halcon显示的小程序 C#用basler相机sdk采集图像并用halcon显示的小程序 本人在用halcon做图像处理做视觉项目时,通常都是用c#写程序的主 ...

  7. basler相机的调试与配置以及多相机同时运行(完整版)

    之前在实验室做过一段时间basler相机的调试与配置工作,现将当时的工作整理汇总,以方便日后再用.注:本博客引用的所有视频链接,皆为自己实验室之前的师兄所录制,当做了我当时这部分工作入门的教学视频. ...

  8. Basler相机环境配置

    Basler相机环境配置|CSDN创作打卡 背景: 最近的项目要用到Basler相机,于是将学习的记录保存下来,方便以后查看,大致分为一下几个步骤:安装软件,配置环境 安装软件 下载最新版本的安装包, ...

  9. ubuntu basler相机opencv

    一.下载安装balser SDK https://www.baslerweb.com/cn/downloads/software-downloads/#type=pylonsoftware 选择5.2 ...

最新文章

  1. ThinkServer TD340服务器安装操作系统[转]
  2. 《Neural Networks for Machine Learning》学习二
  3. JAVA笔记(十四)
  4. 七个你一定会犯的云安全错误
  5. Hadoop HA_Yarn HA 集群的搭建
  6. Java编程到底是用idea好还是eclipse好?
  7. 一个虚拟摄像头Filter(Virtual Cam Capture Filter)
  8. ros使用自动驾驶数据集KITTI【1】介绍与可视化
  9. python羊车门问题_python羊车门问题的正确解答
  10. 前端手把手教你js实现附件预览和下载得功能实现
  11. 【一日一logo_day_35】chi
  12. 主数据治理项目前期调研
  13. 程序员数字_作为社会科学程序员处理不同的数字数据
  14. 2015年腾讯游戏策划岗位笔试题目
  15. COGS-2049 疯狂动物城
  16. 常用邮箱、网盘地址列表
  17. 连续傅里叶变换和离散傅里叶变换的关系
  18. Chrome插件不翻墙安装、离线安装, 插件商店,Fatkun图片批量下载插件
  19. 53、RK3588测试视频编解码和 POE OAK Camera编码结合开发
  20. react-comment评论管理

热门文章

  1. OPS TPS RPS 吞吐量 查询率 事物数目 每秒查询率 每秒处理事物数目
  2. 计算机网络系统工程技术要求,《SZDBZ 5.4-2008 信息系统工程建设技术规范 第4部分 计算机网络系统工程》.pdf...
  3. 最大回撤算法代码实现
  4. Vue之MVVM、Vue实例对象、生命周期
  5. Android M ROM 层拦截电话
  6. Win10使用WMIC提示“WMIC已弃用”
  7. 将yuv图像转为.jpg文件
  8. 用友从“新”出发:“新”在哪里?
  9. uni-app和vue什么关系?
  10. 【无标题】解决最新版discuz3.4安装模板插件提示【对不起,您安装的不是正版应用】