迈创采集卡搭配工业相机二次开发介绍(一)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的取流函数,分成三种连续抓图,单帧抓图,回调抓图
下面,跟着注释,来看一下官方提供的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;
}