MIL acquisition and real-time display

Keywords: Windows

Links to the original text: http://www.cnblogs.com/riasky/p/3455541.html

In fact, we do machine vision on-line image acquisition and processing. The processing results determine the control signals that the computer will give, such as motor motion, so as to achieve real-time visual feedback motion. The acquisition in MIL needs the support of Matrox acquisition board. In this paper, the acquisition of MIL is explained with Matrox Helios board in laboratory as an example.

1. Composition of acquisition system

Speaking of acquisition, first of all, we must understand the composition of a complete acquisition system from hardware to software. The following schematic diagram of acquisition system uses Matrox board and MIL software. The detailed process of various CPU, MCU and GPU communication in the diagram is not expressed, but to illustrate the general process. In the actual process, the complete acquisition system is poor. Not too big. (In the future, I will consider a series of blog posts on machine vision hardware when I have time.


Comparing with the above figure, this paper briefly describes the process of drawing: under the illumination of light source, the reflected light of the object passes through the camera lens on the camera CCD (or CMOS) chip. This process is called Capture. The camera's timing controller controls the time interval to transfer the data from the CCD to the camera's buffer Buffer. This process is called Acquisition. Note that if the Buffer's data is not retrieved in time, the next acquisition will cover the previous data. The camera is connected to the Matrox board inserted into the PCI-E interface. The Time control unit on the board controls the retrieving of data from the Buffer in the camera. This process is called Grab, which is from the camera buffer. Analog or analog signal, in the card will do an A/D conversion through the A/D unit, the data will be converted to the corresponding quantized value stored in the corresponding MIL buffer, this process is called Digtize. Here, the output of Capture and Acquisition in Camera is analog signal. This camera is analog camera. Grab and Digtize are accomplished in Frame Grabber. Generally, Camera Link interface is used between the camera and the card, and 1394 interface is also used for high-speed acquisition. In fact, this is also the practice of most ordinary industrial cameras (13fps-30fps). They output digital signals, called digital cameras, and generally use GigE, 1394 or USB interfaces. Note that here I use four English words named Capture, Acquisition, Grab and Digtize, which can be translated into acquisition. Some words in English have similar meanings but have subtle differences. There is no way to distinguish their meanings clearly in Chinese. In fact, what we usually call acquisition is standing on PC. From the perspective of volume image, it is the general name of these four processes.

When we operate the whole acquisition process in the PC, MIL provides us with the distributed Digitizer object for acquisition, corresponding to the Mdig start function. It is very important to specify a DCF(Device Configure File) file when distributing Digitizer objects. This file defines the frequency and resolution of Grab, etc. Simply speaking, it is the frequency at which the camera timing controller stores data to the camera Buffer and the board timing control unit obtains data from the camera Buffer. Frequency must have a matching relationship. The default MIL installation allows users to set up a default DCF file, which is used by default when distributing Digtizer. MIL provides a series of DCF files corresponding to the camera. If not, you can also customize DCF files in MIL Intellicam. The same camera can use different DCF files when defining Digtizer. The frequency of the set and the size of the collected image, such as Digtizer 1 and Digtizer 2, can be adjusted in real time after defining Digtizer. The corresponding acquisition parameters in DCF can be adjusted by MdigControl function.

The following illustrations illustrate several concepts, which are helpful for you to read the manual:

Acquisition path: From Capture to Acquisition, Grab to Digtize, there are six Acquisition paths for color cameras (RGB each counts one channel, that is, you can use color cameras as monochrome cameras). For monochrome cameras, there are two Acquisition paths, each Acquisition pat. H must contain a Time control unit. Several Digtizers can be connected to each Acquisition path, such as Digtizer 1 and Digitizer2, but only one Digtizer can work on the same Acquisition path at a time. You can pre-assign multiple Digtizers and switch when needed.

Independent acquisition path: A Time control unit can only control one Acquisition path acquisition at a time. If two cameras want to achieve simultaneous acquisition, they must use two Time Control Units. Two Acquisition paths with different Time Control Units are called Independent acquisition path. As shown in the figure, the Acquisition path between the color camera and the monochrome camera is the Independent acquisition path, which can be collected at the same time. Digtizer connected to two Independent acquisition paths can work simultaneously to extract maps.

Data input channel (channel): We often hear that dual-channel acquisition is that the same Time control unit's Capture source is divided into multiple, each called a channel, in the acquisition time can switch acquisition, but not simultaneously acquisition.

Device Number: When allocating Digtizer in MIL, it is required to specify the device number of the first Acquisition path of each channel. MIL automatically calculates the total number of Acquisition paths based on the corresponding DCF file. For example, if R Acquisition path of color camera of channel 0 is M_DEV0, then G Acquisition path and B Acquisition path phases It should be M_DEV1 and M_DEV2. Channel 0 monochrome cameras can only be assigned Device Numbers starting with M_DEV3. If the board has only one Time control unit, it must be specified as M_DEV0 or M_DEFAULT.

2.MIL acquisition and real-time display

The functions of acquisition in MIL begin with Mdig, and the functions of opening acquisition operation are MdigGrab, MdigGrabContinuous and MdigProcess. The functions of these three functions are easy to understand literally. They correspond to single frame acquisition, continuous acquisition and simultaneous processing of acquisition.
Before concretely putting these three functions into practice, one more point should be made clear. Transfer sum between three Buffer s Size and type correspondence. The three Buffers are camera Buffer, PC Buffer (memory) and display Buffer in the order of data transfer. The schematic diagram is as follows:

When we collect data, we use the Mdig function to transfer data from the camera buffer to the PC's memory buffer (in this case, the MIL-defined Buffer), and when we display, we use the Mdisp function to transfer data from the memory buffer to the display Buffer (in this case, the window for display).
Notice here that each of the small squares on the schematic diagram represents a pixel data, and you can see that not every Buffer starts with the same size: if the camera Buffer is larger than the PC Buffer acquisition, it will. Automatically truncate multiple pixels; if the camera Buffer is smaller than the PC Buffer acquisition time will be Automatically start filling from the Buffer's initial point (default upper left corner), the remaining unfilled PC Buffer will remain initialized (so it is usually initialized immediately after the Buffer has been allocated); the transition relationship between PC Buffer and memory Buffer is similar. If the size of adjacent Buffers is different, we can use MdigControl to control the proportion of acquisition (for example, the acquisition ratio is set to 1/2, then the Buffer interval is taken from the camera when acquisition, which is equivalent to 1/2 of the original Buffer interval of the camera), and MdispZoom to control the proportion of display (for example, the display ratio is set to 2, then the display time is from PC. Buffer linear interpolation is twice the original. In addition, if you want to control the initial point of default alignment, you can use MdigControl and MdispPan adjustment period corresponding parameters, generally unchanged, refer to the MIL manual. In order to get the best result of collection, we Instead of making any assumptions about the camera Buffer, the MdigInquire function should be used to query the size and type of the camera Buffer (e.g. 8+M_UNSIGNED), assign the corresponding PC Buffer, and so on. We should not make any assumptions about the display Buffer. We should query the size of the display Buffer and zoom in and out the PC Buffer when displaying it.

MdigGrab

The sample code is as follows
	//Allocate default applications and systems
	MappAllocDefault(M_SETUP, &MilApplication, &MilSystem, M_NULL, M_NULL, M_NULL);

	//Distribution collector
	MdigAlloc(MilSystem, M_DEFAULT, "M_DEFAULT", M_DEFAULT, &MilDigitizer);

	int nGrabScaleSet = 4;//Setting the acquisition ratio

	//Allocate buffer
	if (MsysInquire(MilSystem, M_SYSTEM_TYPE, M_NULL) == M_SYSTEM_HELIOS_TYPE)
	{
		   BufferLocation = M_ON_BOARD;
	}
	MbufAlloc2d(MilSystem, 
				long(MdigInquire(MilDigitizer, M_SIZE_X, M_NULL) / nGrabScaleSet),
				long(MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL) / nGrabScaleSet),
				MdigInquire(MilDigitizer, M_TYPE, M_NULL),
				M_DISP + M_IMAGE + M_GRAB + BufferLocation,
				&MilBufferImage);
	MbufClear(MilBufferImage, 0xFF);

	//Allocation display
	MdispAlloc(MilSystem, M_DEFAULT, "M_DEFAULT",  M_WINDOWED, &MilDisplay);

	//Buffer and Display bindings
	MdispSelectWindow(MilDisplay, MilBufferImage, GetDlgItem(IDS_DISPLAY)->GetSafeHwnd());

	//Single-frame acquisition of two frames
	MdigControl(MilDigitizer, M_GRAB_SCALE_X, 1.0/nGrabScaleSet);
	MdigControl(MilDigitizer, M_GRAB_SCALE_Y, 1.0/nGrabScaleSet);
	MdigControl(MilDigitizer, M_GRAB_MODE, M_ASYNCHRONOUS );
	MdigGrab(MilDigitizer, MilBufferImage);
	Sleep(1000);//Pause for a second
	MdispZoom(MilDisplay, 2, 2);
	MdigGrab(MilDigitizer, MilBufferImage);
	Sleep(1000);//Pause for a second
	
	//Releasing resources
	if (M_NULL != MilBufferImage)
	{
		MbufFree(MilBufferImage);
	}
	if (M_NULL != MilDisplay)
	{
		MdispFree(MilDisplay);
	}
	if (M_NULL != MilDigitizer)
	{
		MdigFree(MilDigitizer);
	}
	if (M_NULL != MilApplication)
	{
		MappFreeDefault(MilApplication, MilSystem, M_NULL, M_NULL, M_NULL);
	}
MdigGrab is very simple. It grabs a frame from camera Buffer to PC memory Buffer every time. Notice that we use MdigInquire function to query the size and distribution of camera Buffer. MdigControl controls the collection ratio. The size and type of PC Buffer and camera Buffer allocated here are matched, but PC Buffer and display Buffer here are matched. Fer (window size) is different. Readers can handle it themselves (Get Windows Rect and DisplaZoom).
It should also be noted that there are two basic modes of acquisition, asynchronism and synchronization, and generally acquisition asynchronism (M_ASYNCHRONOUS). For the specific meaning, please consult the MIL manual.

MdigGrabContinuous

Start continuous acquisition
	//Allocate default applications and systems
	MappAllocDefault(M_SETUP, &MilApplication, &MilSystem, M_NULL, M_NULL, M_NULL);
	
	//Distribution collector
	MdigAlloc(MilSystem, M_DEFAULT, "M_DEFAULT", M_DEFAULT, &MilDigitizer);
	
	int nGrabScaleSet = 4;//Setting the acquisition ratio
	
	//Allocate buffer
	if (MsysInquire(MilSystem, M_SYSTEM_TYPE, M_NULL) == M_SYSTEM_HELIOS_TYPE)
	{
		   BufferLocation = M_ON_BOARD;
	}
	MbufAlloc2d(MilSystem, 
				long(MdigInquire(MilDigitizer, M_SIZE_X, M_NULL) / nGrabScaleSet),
				long(MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL) / nGrabScaleSet),
				MdigInquire(MilDigitizer, M_TYPE, M_NULL),
				M_DISP + M_IMAGE + M_GRAB + BufferLocation,
				&MilBufferImage);
	MbufClear(MilBufferImage, 0xFF);
	
	//Allocation display
	MdispAlloc(MilSystem, M_DEFAULT, "M_DEFAULT",  M_WINDOWED, &MilDisplay);
	
	//Buffer and Display bindings
	MdispSelectWindow(MilDisplay, MilBufferImage, GetDlgItem(IDS_DISPLAY)->GetSafeHwnd());
	
	//Start continuous acquisition
	MdigGrabContinuous(MilDigitizer, MilBufferImage);
Close continuous acquisition
	MdigHalt(MilDigitizer);

	//Releasing resources
	if (M_NULL != MilBufferImage)
	{
		MbufFree(MilBufferImage);
	}
	if (M_NULL != MilDisplay)
	{
		MdispFree(MilDisplay);
	}
	if (M_NULL != MilDigitizer)
	{
		MdigFree(MilDigitizer);
	}
	if (M_NULL != MilApplication)
	{
		MappFreeDefault(MilApplication, MilSystem, M_NULL, M_NULL, M_NULL);
	}
Note that MdigGrabContinuous is an asynchronous acquisition mode. It is directly sent to the display memory in the acquisition process. It is not saved in the MilBuffer Image. Only the last frame after stopping acquisition is saved in the MilBuffer Image. It is generally used to realize the online observation function. In order to achieve real-time image capture and processing, only MdigGrab and MdigP can be used. Rocess function.

MdigProcess

Start collecting
	// TODO: Add your control notification handler code here
	//Allocate default applications and systems
	MappAllocDefault(M_SETUP, &MilApplication, &MilSystem, M_NULL, M_NULL, M_NULL);

	//Distribution collector
	MdigAlloc(MilSystem, M_DEFAULT, "M_DEFAULT", M_DEFAULT, &MilDigitizer);

	//Allocate display buffer
	MbufAlloc2d(MilSystem, 
				long(MdigInquire(MilDigitizer, M_SIZE_X, M_NULL)),
				long(MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL)),
				MdigInquire(MilDigitizer, M_TYPE, M_NULL),
				M_DISP + M_IMAGE,
				&MilBufferImage);
	MbufClear(MilBufferImage, 0xFF);

	//Allocation display
	MdispAlloc(MilSystem, M_DEFAULT, "M_DEFAULT",  M_WINDOWED, &MilDisplay);
	
	//Buffer and Display bindings
	MdispSelectWindow(MilDisplay, MilBufferImage, GetDlgItem(IDS_DISPLAY)->GetSafeHwnd());

	
	/************************************************************************/
	/* Assign Buffer List */
	/************************************************************************/
    MappControl(M_ERROR, M_PRINT_DISABLE);
    
	//Initialize buffer list
	for(m = 0; m < BUFFERING_SIZE_MAX; m++)
	{
		MilGrabBufferList[m] = M_NULL;
	}
	
	//Allocate as many buffer list s as possible
	if (MsysInquire(MilSystem, M_SYSTEM_TYPE, M_NULL) == M_SYSTEM_HELIOS_TYPE)
	{
		BufferLocation = M_ON_BOARD;
	}
	MilGrabBufferListSize=0;
	for(m = 0; m < BUFFERING_SIZE_MAX; m++)
	{
		//Assign a Buffer
		MbufAlloc2d(MilSystem,
					MdigInquire(MilDigitizer, M_SIZE_X, M_NULL),
					MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL), 
					MdigInquire(MilDigitizer, M_TYPE, M_NULL), 
					M_IMAGE+M_GRAB+M_PROC+BufferLocation, 
					&MilGrabBufferList[m]);
		
		if (MilGrabBufferList[m])//Initialization if allocation is successful
		{
			MbufClear(MilGrabBufferList[m], 0xFF);
			
			LastAllocatedM = m;
			MilGrabBufferListSize++;
		}
		else//If the allocation fails, the allocation stops.
		{
			break;
		}
	}

	MappControl(M_ERROR, M_PRINT_ENABLE);
	
	//Prevent running out of memory and release the last buffer
	MbufFree(MilGrabBufferList[LastAllocatedM]);
	MilGrabBufferList[LastAllocatedM] = M_NULL;
	MilGrabBufferListSize--;//Note that the size-1 must be released here, otherwise MdigProcess detection will be called.
							//When the actual available buffer size does not match the imported size parameter, an error will be reported.

	/************************************************************************/
	/*Acquisition and processing*/
	/************************************************************************/
	//Setting up the data to be passed
	UserHookData.MilImageDisp        = MilBufferImage;
	UserHookData.ProcessedImageCount = 0;
    
	MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize,
                M_START, M_DEFAULT, ProcessingFunction, &UserHookData); 
Stop acquisition
	/************************************************************************/
	/*Stop acquisition and processing*/
	/************************************************************************/
	MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize,
				M_STOP, M_DEFAULT, ProcessingFunction, &UserHookData);

	//Releasing resources
    MappControl(M_ERROR, M_PRINT_DISABLE);
	for (m = 0; m < BUFFERING_SIZE_MAX; m++)
	{
		if(M_NULL != MilGrabBufferList[m])
		{
			MbufFree(MilGrabBufferList[m]);
			MilGrabBufferList[m] = M_NULL;
		}
	}
	if (M_NULL != MilBufferImage)
	{
		MbufFree(MilBufferImage);
	}
	if (M_NULL != MilDisplay)
	{
		MdispFree(MilDisplay);
	}
	if (M_NULL != MilDigitizer)
	{
		MdigFree(MilDigitizer);
	}
    MappControl(M_ERROR, M_PRINT_ENABLE);

	if (M_NULL != MilApplication)
	{
		MappFreeDefault(MilApplication, MilSystem, M_NULL, M_NULL, M_NULL);
	}
Acquisition callback function
long MFTYPE ProcessingFunction(long HookType, MIL_ID HookId, void MPTYPE *HookDataPtr)
{
	HookDataStruct *UserHookDataPtr = (HookDataStruct *)HookDataPtr;
	MIL_ID ModifiedBufferId;
	char   Text[10]= {'\0'};
	
	//Get the buffer list to get the buffer number of the collected data
	MdigGetHookInfo(HookId, M_MODIFIED_BUFFER+M_BUFFER_ID, &ModifiedBufferId);   
	
	UserHookDataPtr->ProcessedImageCount++;
	
	//Write the acquisition number on the current picture
	MOs_ltoa(UserHookDataPtr->ProcessedImageCount, Text, 10);
	MgraText(M_DEFAULT, ModifiedBufferId, 10, 10, Text);
	
	//Copy the processed Buffer data to the display buffer
	MbufCopy(ModifiedBufferId, UserHookDataPtr->MilImageDisp);
	
	return 0;
}
In principle, we recommend using MdigProcess function. First, we can use multi-Buffer to optimize the performance of the program. Secondly, it gives us a powerful control over the acquisition process. We can process the collected image or save every frame in real time in the acquisition callback function (which is also the principle of the realization of MIL video recording function). In the example, I demonstrated using a callback function to add a serial number to each frame captured.

I've written the program annotations very clearly. I believe that it's not a big problem to write a complete acquisition program in combination with the MIL manual.

Complete Code File in Blog Download link

Originality, reprint please indicate from http://blog.csdn.net/wenzhou1219






 

Reprinted at: https://www.cnblogs.com/riasky/p/3455541.html

Posted by Harry57 on Sat, 27 Jul 2019 08:04:15 -0700