Using Euresys Multicam Library
There are several different frame grabbers and industrial cameras available in my Lab for experiment. One of them is from Euresys (sorry, this is not an advertisement) and there are several other brands. However most of the time I'm dealing with this card either with analog cameras (standard analog interface) or digital cameras (with cameralink interface).
I found that this library is very convenient to use. The disadvantage is that like other available SDK's, I found that the guide of the SDK is not quite human readable. So I was trying hard to understand how to use this, and happens to be after a lot of attempts (try, fail, ask support, fail, try again, etc.) I can understand some this library.
Therefore I want to write how to use this library in this blog. So if I have to use it again in the future, I can read it from this blog and so can you :). If there's some part that is not correct, please give a feedback to me. Thanks.
The process of using this library is divided into three parts:
1. Initialization, includes the initialization of the card(s), camera(s) and the callback function.
2. Image acquisition.
3. Stop image acquisition and memory cleanup.
Let's start from the first part, initialization. Depending on your coding platform, you can write your own code. I'm using C++ on a Borland C++ Builder compiler, if you're using Visual C++ then you might need to adjust this code to your coding platform. I use the sample code provided from Euresys.
- Board and camera initialization
1. Initialization of driver
McOpenDriver(NULL);
2. Setting error message configuration
// Activate message box error handling
McSetParamInt(MC_CONFIGURATION, MC_ErrorHandling, MC_ErrorHandling_MSGBOX);
McSetParamStr(MC_CONFIGURATION, MC_ErrorLog, "error.log");
3. Setting board topology (check your board)
McSetParamInt(MC_BOARD + 1, MC_BoardTopology, MC_BoardTopology_MONO);
4. Creating a channel
McCreate(MC_CHANNEL, &m_Channel);
McSetParamInt(m_Channel, MC_DriverIndex, 1);
- Creating a connection to a camera
1. Choose the channel for the camera (depends on the port).
McSetParamStr(m_Channel, MC_Connector, "M");
2. Select the cam file, check your camera
McSetParamStr(m_Channel, MC_CamFile, "VCC-G22V31CL_P120SC");
3. Set the exposure time
McSetParamInt(m_Channel, MC_Expose_us, 10000);
4. Set the color format
McSetParamInt(m_Channel, MC_ColorFormat, MC_ColorFormat_Y8);
5. Set the acquisition mode
McSetParamInt(m_Channel, MC_AcquisitionMode, MC_AcquisitionMode_HFR);
- Setting the trigger mode
1. Choose the way the first acquisition is triggered
McSetParamInt(m_Channel, MC_TrigMode, MC_TrigMode_IMMEDIATE);
2. Choose the triggering mode for subsequent acquisitions
McSetParamInt(m_Channel, MC_NextTrigMode, MC_NextTrigMode_REPEAT);
3. Choose the number of images to acquire
McSetParamInt(m_Channel, MC_SeqLength_Fr, MC_INDETERMINATE);
- Setting up the frame parameters
1. Retrieve image dimensions
McGetParamInt(m_Channel, MC_ImageSizeX, &m_SizeX);
McGetParamInt(m_Channel, MC_ImageSizeY, &m_SizeY);
McGetParamInt(m_Channel, MC_BufferPitch, &m_BufferPitch);
2. The memory allocation for the images is automatically done by Multicam when activating the channel. We only set the number of surfaces to be created by MultiCam.
McSetParamInt(m_Channel, MC_SurfaceCount, EURESYS_SURFACE_COUNT);
- Enabling Multicam Signals
1. Enable MultiCam signals
McSetParamInt(m_Channel, MC_SignalEnable + MC_SIG_SURFACE_PROCESSING, MC_SignalEnable_ON);
McSetParamInt(m_Channel, MC_SignalEnable + MC_SIG_ACQUISITION_FAILURE, MC_SignalEnable_ON);
2. Register the callback function
McRegisterCallback(m_Channel, GlobalCallback, this);
- Preparing bitmap info
1. Build bitmap info Y8
m_pBitmapInfo = (BITMAPINFO *) new BYTE[sizeof(BITMAPINFO) + 255*sizeof(RGBQUAD)];
m_pBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
m_pBitmapInfo->bmiHeader.biPlanes = 1;
m_pBitmapInfo->bmiHeader.biBitCount = 8;
m_pBitmapInfo->bmiHeader.biCompression = BI_RGB;
m_pBitmapInfo->bmiHeader.biSizeImage = 0;
m_pBitmapInfo->bmiHeader.biXPelsPerMeter = 0;
m_pBitmapInfo->bmiHeader.biYPelsPerMeter = 0;
m_pBitmapInfo->bmiHeader.biClrUsed = 0;
m_pBitmapInfo->bmiHeader.biClrImportant = 0;
for (int i = 0 ; i <>
{
m_pBitmapInfo->bmiColors[i].rgbBlue = (BYTE)i;
m_pBitmapInfo->bmiColors[i].rgbGreen = (BYTE)i;
m_pBitmapInfo->bmiColors[i].rgbRed = (BYTE)i;
m_pBitmapInfo->bmiColors[i].rgbReserved = 0;
}
m_pBitmapInfo->bmiHeader.biWidth = m_BufferPitch / (m_pBitmapInfo->bmiHeader.biBitCount/8) ;
m_pBitmapInfo->bmiHeader.biHeight = -(int)m_SizeY ;
- Declaring the callback function
void WINAPI GlobalCallback(PMCSIGNALINFO SigInfo)
{
if (SigInfo && SigInfo->Context)
{
TForm1* pTForm1 = (TForm1*) SigInfo->Context ;
pTForm1->Callback(SigInfo);
}
}
- Callback function
void TForm1::Callback(PMCSIGNALINFO SigInfo)
{
if (SigInfo->Signal == MC_SIG_SURFACE_PROCESSING)
{
// Update "current" surface address pointer
McGetParamInt(SigInfo->SignalInfo, MC_SurfaceAddr, (PINT32) &m_pCurrent);
//----------------------------------------
//
// Insert the eVision code here.
//
//----------------------------------------
// Post screen refresh message
RECT recpict;
recpict.left = 0;
recpict.top = 0;
recpict.right = m_SizeX-1;
recpict.bottom = m_SizeY-1;
InvalidateRect(Handle, &recpict, false);
}
else if (SigInfo->Signal == MC_SIG_ACQUISITION_FAILURE)
{
StatusBar1->SimpleText = m_StatusBarText.sprintf("Frame Rate: %.2f, Channel State: IDLE", 0);
MessageBox(NULL, "Acquisition Failure !", "PicoloVideoTrigger", MB_OK);
}
}
- Start and Stop Grabbing
1. Start an acquisition sequence by activating the channel
McSetParamInt(m_Channel, MC_ChannelState, MC_ChannelState_ACTIVE);
2. Stop an acquisition sequence by deactivating the channel
McSetParamInt(m_Channel, MC_ChannelState, MC_ChannelState_IDLE);
- Deactivating Channel and Cleaning Up
1. Set the channel to IDLE before deleting it.
McSetParamInt(m_Channel, MC_ChannelState, MC_ChannelState_IDLE);
2. Delete the channel
McDelete(m_Channel);
3. Terminate driver
McCloseDriver();
4. Delete bitmap info
if (m_pBitmapInfo) delete m_pBitmapInfo;
That's all, I will post the details in the next article because it's too long to be posted here.
Labels: euresys, image acquisition, work