当前位置:AIGC资讯 > 数据采集 > 正文

迈创采集卡搭配工业相机二次开发介绍(一)

迈创采集卡搭配工业相机二次开发介绍(一)SDK简介

迈创采集卡介绍 迈创采集卡SDK简介 MIL SDK获取路径 接口函数说明 MIL接口简单介绍

迈创采集卡介绍

MIL全称为Matrox Imaging Library,由加拿大Matrox公司开发;MIL软件包是一个独立于硬件的、含有多个标准模块或组件的图像库,可以对图像进行采集、处理、分析、显示和存取操作,其功能覆盖图像领域的所有方面,使用起来也相当简单和方便;
MIL-Lite是MIL的子集,含有MIL的部分模块,可以进行图像的采集、显示、存取操作,还可以在图像上进行图形操作及LUT变换等;
MIL/MIL-Lite支持Matrox公司所有采集卡,如果应用程序采用其它公司的采集卡,则不能使用MIL/MIL-Lite的采集功能,但应用程序可以使用MIL/MIL-Lite的其它功能。
在工作中呢,主要接触到迈创的cameralink采集卡、coxpress采集卡,型号例如:CML;solios系列的的SOL 2M EV CLF、SOL 6M CLB E,CXP:rapixo的RAP 4G 4C6 、RAP 4G 4C12
虽然采集卡型号多,但是mil二次开发的基本思路是一样的

迈创采集卡SDK简介

首先,要理解MIL中的五大基本对象,如下图:

Application:用户开发的一个应用程序,一般应用程序同一时刻只存在一个Application对象。主要用它来提供一个用于控制和执行MIL应用程序的基本环境

System:System代表为一个包含CPU或GPU、内存或显存和图像控制器的单元分配的一个虚拟访问对象,例如一张Matrox采集卡、一台工控机都可以被分配为一个System。System能够通过加上相机和显示器来采集、保存和显示。每个Application下可以包含多个System,这就好比一台电脑可以插上多块Matrox采集卡

Display:Display对应显示。所有和显示的操作都是靠它来完成。这个在手册中提到了两种Display:一种是MIL内建的用于演示的Display叫Auxiliary Display,它不适用于Windows Desktop,主要用于和Matrox显卡配套使用的Screen,一般用不上,不予讨论;另一种是叫Windowed Display,其中一种是MIL用于演示的Display,不需要选择要显示的窗口句柄,默认分配的Display对象是此种display,另一种是用户选择要显示的窗口句柄,这个需要你自己选择在哪个windows窗体上显示对应的Buffer图像内容

Digitizer:Digitizer对应取图。它用于图像的采集和相机属性的调整等,和取图有关的操作都是靠它来完成。

Buffer:Buffer对应一块内存,可以对它赋予不同的属性用来对图像作相应处理,如存储、显示、采集、处理,只有赋予了对应的属性的Buffer才能用于对应操作,只赋予了保存属性的Buffer是不能用于显示的。

了解了这个5个基本概念有什么用呢,对于做工业相机二次开发来讲,很重要,它们决定了你代码开发的顺序与逻辑

MIL SDK获取路径

1、安装MIL客户端,目前MIL已经更新到MIL10、MILX 版本,搭配其最新的采集卡
2、安装完mil后,打开Matrox Imaging Library,即可找到sdk例程与帮助文档

3、结合工业相机,常用的两个例程试MdigGrab与MdigProcess两个,参考这两个例程即可

接口函数说明

mil与工业相机取流过程,主要分为三个步骤

MIL初始化,初始化app、systerm、digitizer、buffer等资源、初始化相机参数 MIL取流,使用取流函数,获取图像,使用相机控制函数,控制相机出图节拍 MIL资源释放,释放app、systerm、digitizer、buffer等资源

MIL接口简单介绍

MIL的初始化与资源释放需要严格按照顺序进行
1、初始化定义mil的各种变量

		MIL_ID MilApplication,  /* Application identifier.  */
		MilSystem,       /* System identifier.       */
		MilDisplay,      /* Display identifier.      */
		MilDigitizer,    /* Digitizer identifier.    */ 
		MilImage;        /* Image buffer identifier. */

2、初始app、systerm、digitizer
不管你使用多少个相机,使用多少张采集卡,同一时间,只有一个app在运行;
MsysAlloc这里需要注意第一个参数,M_SYSTEM_SOLIOS以为着我们使用的采集类型,不同的采集卡,使用不同的参数;
MdigAlloc的第三个参数,通常是传入dcf路径的,官方给的示例,往往传入的是M_DEFAULT默认值,那么就需要在milconfig中进行配置

MappAlloc(M_DEFAULT,&MilApplication);
MsysAlloc(M_SYSTEM_SOLIOS, M_DEFAULT, M_DEFAULT, &MilSystem);
MdigAlloc(MilSystem, M_DEV0, "./dcf/1.dcf", M_DEFAULT, &MilDigitizer);
MdispAlloc(MilSystem, M_DEFAULT, "M_DEFAULT", M_DEFAULT, &MilDisplay);//我们往往不会用到MilDisplay,所以,可以考虑注释掉它,节约内存

上面的三个接口,都是分开初始化app、systerm、digitizer,具备更多的灵活性,当然也可以使用MappAllocDefault,进行默认配置,如下面的接口

MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem,&MilDisplay, &MilDigitizer, &MilImage);

使用MappAllocDefault,那么默认的卡选项,dcf路径,都需在milconfig中进行配置,如下图所示:

3、分配buffer,获取图像宽高

分配buffer呢,有多种情况需要考虑,例如黑白相机,彩色相机,8位图像,10位图像,12位图像,彩色bayer格式,彩色RGB格式等
黑白统一使用MbufAlloc2d这个接口,彩色要使用MbufAllocColor或者MbufAllocColor2d

	MIL_INT BufSizeX;
	MIL_INT BufSizeY;
	MdigInquire(MilDigitizer, M_SIZE_X,    &BufSizeX);//读取采集卡中的图像宽度
	MdigInquire(MilDigitizer, M_SIZE_Y,    &BufSizeY);//读取采集卡中的图像高度
	MbufAlloc2d(MilSystem, BufSizeX,BufSizeY,8L+M_UNSIGNED, M_IMAGE+M_GRAB+M_DISP, &MilImage);//分配一个8位的黑白图像buffer用于取流
	MbufClear(MilImage, 0);

4、取流函数
mil的取流函数,分成三种连续抓图,单帧抓图,回调抓图

连续抓图使用MdigGrabContinuous,搭配MdigHalt(停止采集使用),一般不推荐使用连续抓图 单帧抓图MdigGrab,从指定的相机digitizer中获取一张图片,搭配MdigGrabWait,可以在指定超时时间内获取一帧数据 回调抓图MdigProcess,支持同步与异步回调两种
下面,跟着注释,来看一下官方提供的MdigProcess例程,结合上面简单讲的,应该就能更好的理解mil sdk开发逻辑
/***************************************************************************************/
/*
 * File name: MdigProcess.cpp
 *
 * Synopsis:  This program shows the use of the MdigProcess() function and its multiple
 *            buffering acquisition to do robust real-time processing.
 *
 *            The user's processing code to execute is located in a callback function 
 *            that will be called for each frame acquired (see ProcessingFunction()).
 *
 *      Note: The average processing time must be shorter than the grab time or some
 *            frames will be missed. Also, if the processing results are not displayed
 *            and the frame count is not drawn or printed, the CPU usage is reduced 
 *            significantly.
 *
 * Copyright © Matrox Electronic Systems Ltd., 1992-2021.
 * All Rights Reserved
 */
#include <mil.h>

/* Number of images in the buffering grab queue.
   Generally, increasing this number gives a better real-time grab.
 */
#define BUFFERING_SIZE_MAX 20

/* User's processing function prototype. */
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr);

/* User's processing function hook data structure. */
typedef struct
   {
   MIL_ID  MilDigitizer;
   MIL_ID  MilImageDisp;
   MIL_INT ProcessedImageCount;
   } HookDataStruct;


/* Main function. */
/* ---------------*/

int MosMain(void)
{
   MIL_ID MilApplication;
   MIL_ID MilSystem     ;
   MIL_ID MilDigitizer  ;
   MIL_ID MilDisplay    ;
   MIL_ID MilImageDisp  ;
   MIL_ID MilGrabBufferList[BUFFERING_SIZE_MAX] = { 0 };
   MIL_INT MilGrabBufferListSize;
   MIL_INT ProcessFrameCount   = 0;
   MIL_DOUBLE ProcessFrameRate = 0;
   MIL_INT NbFrames = 0, n = 0;
   HookDataStruct UserHookData;
//上面都是初始化后面要用到的各种变量

   /* Allocate defaults. */
   //使用MappAllocDefault默认分配app、system等资源,也可以使用MappAlloc、MsysAlloc等函数,单独分配
   MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, &MilDisplay,&MilDigitizer, M_NULL);

   /* Allocate a monochrome display buffer. */
   //申请一块黑白的8位图像缓存
   MbufAlloc2d(MilSystem,
      MdigInquire(MilDigitizer, M_SIZE_X, M_NULL),
      MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL),
      8 + M_UNSIGNED,
      M_IMAGE + M_GRAB + M_PROC + M_DISP,
      &MilImageDisp);
   MbufClear(MilImageDisp, M_COLOR_BLACK);

   /* Display the image buffer. */
   //锁定显示窗口,使用mil的显示窗
   MdispSelect(MilDisplay, MilImageDisp);

   /* Print a message. */
   MosPrintf(MIL_TEXT("\nMULTIPLE BUFFERED PROCESSING.\n"));
   MosPrintf(MIL_TEXT("-----------------------------\n\n"));
   MosPrintf(MIL_TEXT("Press <Enter> to start processing.\n\n"));

   /* Grab continuously on the display and wait for a key press. */
   //演示连续抓图,直到调用MdigHalt停止
   MdigGrabContinuous(MilDigitizer, MilImageDisp);
   MosGetch();//键盘暂停命令

   /* Halt continuous grab. */
   MdigHalt(MilDigitizer);

   /* Allocate the grab buffers and clear them. */
   MappControl(M_DEFAULT, M_ERROR, M_PRINT_DISABLE);//关闭弹窗打印报错信息
   //申请一串buffer,用于回调取流,跟MilImageDisp类似,主要去看BUFFERING_SIZE_MAX,默认申请了20个buffer缓存,避免回调阻塞
   
   for (MilGrabBufferListSize = 0; MilGrabBufferListSize<BUFFERING_SIZE_MAX;
      MilGrabBufferListSize++)
      {
      MbufAlloc2d(MilSystem,
         MdigInquire(MilDigitizer, M_SIZE_X, M_NULL),
         MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL),
         8 + M_UNSIGNED,
         M_IMAGE + M_GRAB + M_PROC,
         &MilGrabBufferList[MilGrabBufferListSize]);
      if (MilGrabBufferList[MilGrabBufferListSize])
         MbufClear(MilGrabBufferList[MilGrabBufferListSize], 0xFF);
      else
         break;
      }
   MappControl(M_DEFAULT, M_ERROR, M_PRINT_ENABLE);//开启弹窗打印报错信息

   /* Initialize the user's processing function data structure. */
   //回调里面自定义的一些变量初始化,用户也可以自己加一下变量,初始化就行
   UserHookData.MilDigitizer        = MilDigitizer;
   UserHookData.MilImageDisp        = MilImageDisp;
   UserHookData.ProcessedImageCount = 0;
   
   /* Start the processing. The processing function is called with every frame grabbed. */
   //开启回调函数M_START,MilGrabBufferList就是我们想要的buffer
   MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize,
               M_START, M_DEFAULT, ProcessingFunction, &UserHookData);


   /* Here the main() is free to perform other tasks while the processing is executing. */
   /* --------------------------------------------------------------------------------- */


   /* Print a message and wait for a key press after a minimum number of frames. */
   MosPrintf(MIL_TEXT("Press <Enter> to stop.                    \n\n"));
   MosGetch();

   /* Stop the processing. */
   //关闭回调函数M_STOP
   MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize,
               M_STOP, M_DEFAULT, ProcessingFunction, &UserHookData);

   /* Print statistics. */
   MdigInquire(MilDigitizer, M_PROCESS_FRAME_COUNT,  &ProcessFrameCount);//获取一下回调里面的统计信息,帧号
   MdigInquire(MilDigitizer, M_PROCESS_FRAME_RATE,   &ProcessFrameRate);
   MosPrintf(MIL_TEXT("\n\n%d frames grabbed at %.1f frames/sec (%.1f ms/frame).\n"),
                        (int)ProcessFrameCount, ProcessFrameRate, 1000.0/ProcessFrameRate);
   MosPrintf(MIL_TEXT("Press <Enter> to end.\n\n"));
   MosGetch();

   /* Free the grab buffers. */
   //清除缓存,注意顺序
   while(MilGrabBufferListSize > 0)
         MbufFree(MilGrabBufferList[--MilGrabBufferListSize]);

   /* Free display buffer. */
   MbufFree(MilImageDisp);

   /* Release defaults. */
   //也有单独释放每一个关键角色的函数
   MappFreeDefault(MilApplication, MilSystem, MilDisplay, MilDigitizer, M_NULL);

   return 0;
}


/* User's processing function called every time a grab buffer is ready. */
/* -------------------------------------------------------------------- */

/* Local defines. */
#define STRING_LENGTH_MAX  20
#define STRING_POS_X       20
#define STRING_POS_Y       20
//回调函数啦
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr)
   {
   HookDataStruct *UserHookDataPtr = (HookDataStruct *)HookDataPtr;
   MIL_ID ModifiedBufferId;
   MIL_TEXT_CHAR Text[STRING_LENGTH_MAX]= {MIL_TEXT('\0'),};

   /* Retrieve the MIL_ID of the grabbed buffer. */
   MdigGetHookInfo(HookId, M_MODIFIED_BUFFER+M_BUFFER_ID, &ModifiedBufferId);

   /* Increment the frame counter. */
   UserHookDataPtr->ProcessedImageCount++;

   /* Print and draw the frame count (remove to reduce CPU usage). */
   MosPrintf(MIL_TEXT("Processing frame #%d.\r"), (int)UserHookDataPtr->ProcessedImageCount);
   MosSprintf(Text, STRING_LENGTH_MAX, MIL_TEXT("%d"), (int)UserHookDataPtr->ProcessedImageCount);
   MgraText(M_DEFAULT, ModifiedBufferId, STRING_POS_X, STRING_POS_Y, Text);

   /* Execute the processing and update the display. */
   MimArith(ModifiedBufferId, M_NULL, UserHookDataPtr->MilImageDisp, M_NOT);
   //ModifiedBufferId是我们想要的图像buffer
   return 0;
   }

更新时间 2023-11-08