VisionMaster4.2.0 联合C#实现相机SDK取图
一般情况下,VisionMater支持绝大多数工业相机直连,但是在实际使用过程中,例如相机需要被其他软件占用等复杂情况,VisionMaster无法连接相机获取图像数据。为此,VisionMaster图像源支持二次开发情况下,利用SDK获取图像数据。今天,简单介绍一下工业相机取流以及VisionMaster的SDK取图。
一、相机取流
这里采用海康MVS相机SDK,完成相机的取流。
1.1 设备连接接口流程
详细步骤:
-
(可选)调用MV_CC_EnumDevices_NET() 枚举子网内指定传输协议对应的所有设备。可以通过nTLayerType在结构 MV_CC_DEVICE_INFO() 中找到设备的信息。
-
(可选)在打开指定设备之前,调用 MV_CC_IsDeviceAccessible_NET() 检查指定设备是否可访问。
-
调用 MV_CC_CreateDevice_NET() 以创建设备句柄。
-
调用 MV_CC_OpenDevice_NET() 打开设备。
-
(可选)执行以下一个或多个操作:
获取设备信息 调用 MV_CC_GetAllMatchInfo_NET()
获得最佳包大小(仅对网口相机有效) 调用 MV_CC_GetOptimalPacketSize_NET()
-
调用 MV_CC_CloseDevice_NET() 关闭设备。
-
调用 MV_CC_DestroyDevice_NET() 来销毁句柄并释放资源。
1.2 主动取流
SDK提供主动获取图像的接口,用户可以在开启取流后直接调用此接口获取图像,也可以使用异步方式(线程、定时器等)获取图像。
- 主动取流有两种方式(不可以同时使用)
方式一:调用 MV_CC_StartGrabbing_NET() 开始采集,需要自己开启一个buffer,然后在应用层循环调用 MV_CC_GetOneFrameTimeout_NET() 获取指定像素格式的帧数据,获取帧数据时上层应用程序需要根据帧率控制好调用该接口的频率。
方式二:调用 MV_CC_StartGrabbing_NET() 开始采集,然后在应用层调用 MV_CC_GetImageBuffer_NET() 获取指定像素格式的帧数据,然后调用 MV_CC_FreeImageBuffer_NET() 释放buffer,获取帧数据时上层应用程序需要根据帧率控制好调用该接口的频率。
- 区别:
1、 MV_CC_GetImageBuffer_NET() 需要与 MV_CC_FreeImageBuffer_NET() 配套使用,当处理完取到的数据后,需要用 MV_CC_FreeImageBuffer_NET() 接口将pstFrame内的数据指针权限进行释放。
2、 MV_CC_GetImageBuffer_NET() 与 MV_CC_GetOneFrameTimeout_NET() 相比,有着更高的效率。且其取流缓存的分配是由sdk内部自动分配的,而 MV_CC_GetOneFrameTimeout_NET() 接口是需要客户自行分配。
- 采集流程(以MV_CC_GetImageBuffer_NET为例)
1.3 回调取流
SDK提供注册回调函数的接口,用户可以将自己定义的回调函数注册在SDK内部,SDK获取到相机图像会主动回调到应用程序供用户处理,此方式可以简化用户程序逻辑。
- 采集流程
- 注意事项:
1、回调函数中不建议有耗时操作、线程锁等,容易造成回调阻塞。
2、pData返回的是一个地址指针,建议将pData里面的数据copy出来另建线程使用。
示例(伪代码):
//创建设备列表
MyCamera.MV_CC_DEVICE_INFO_LIST m_stDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
//返回成功或错误信息
int nRet;
//回调函数
public static MyCamera.cbOutputExdelegate ImageCallback;
void ImageCallbackFunc(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
{
//放入自己的操作
}
// ch:枚举设备 | en:Enum device
nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_stDeviceList);
// ch:获取选择的设备信息 | en:Get selected device information
MyCamera.MV_CC_DEVICE_INFO device =(MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[Index],typeof(MyCamera.MV_CC_DEVICE_INFO));//Index 设备索引
// ch:创建设备 | en:Create device
public MyCamera m_MyCamera = new MyCamera();//创建设备对象
nRet = m_MyCamera.MV_CC_CreateDevice_NET(ref device);
// ch:打开设备 | en:Open device
nRet = m_MyCamera.MV_CC_OpenDevice_NET(ref device);
// ch:注册回调函数 | en:Register image callback
ImageCallback = new MyCamera.cbOutputExdelegate(ImageCallbackFunc);
nRet = m_MyCamera.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero);
// ch:开启抓图 || en: Start grab image
nRet = m_MyCamera.MV_CC_StartGrabbing_NET();
// ch:停止抓图 | en:Stop grab image
nRet = m_MyCamera.MV_CC_StopGrabbing_NET();
// ch:关闭设备 | en:Close device
nRet = m_MyCamera.MV_CC_CloseDevice_NET();
// ch:释放资源 | en:Drstory device
nRet = m_MyCamera.MV_CC_DestroyDevice_NET();
二、VisionMaster 图像源SDK取图
简单搭建测试方案,设置图像源为SDK。
我们通过相机SDK取流,将图像数据拷贝并传给图像源模块中。
伪代码如下:
//用于拷贝出相机图像数据
public ImageBaseData stInputImageInfo;
//相机回调函数
void ImageCallbackFunc(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
{
byte[] m_BufForDriver1 = new byte[pFrameInfo.nFrameLen];
//海康相机取流 指针转byte[]
Marshal.Copy(pData, m_BufForDriver1, 0, ((int)pFrameInfo.nFrameLen));
stInputImageInfo = new ImageBaseData(m_BufForDriver1, pFrameInfo.nFrameLen, pFrameInfo.nWidth, pFrameInfo.nHeight, 1);
}
//实例化图像源,传入相机图像数据stInputImageInfo
ImageSourceModuleTool imageSourceModuleTool = VmSolution.Instance["流程1.图像源1"] as ImageSourceModuleTool;
imageSourceModuleTool.SetImageData(stInputImageInfo);
//流程执行
VmProcedure vmProcedure = VmSolution.Instance["流程1"] as VmProcedure;
vmProcedure.Run();
- 通过接口函数ImageBaseData(byte[] imageData, uint dataLen, int width, int height, int pixelformat)将数据转换为VisionMaster的图像数据类型ImageBaseData。
效果展示: