Since the release of the Automation Technology C6 series there are some changes required in the image acquisiton method of you CVB application. AT C6 features MultiPart an thus regularly requires the 3rd Generation image acquisition stack of CVB.
The C5 cameras from Automation Technology used to transmitt the acuired data containing Range, Intensity and Scatter data in an interlaced format. In this format a transmitted image would look like this line by line:
Intensity Line 0
Scatter Line 0
Range Line 0
Intensity Line 1
Scatter Line 1
Range Line 1
Intensity Line 2
…
While this was a fine way of transmitting associated data it was limited to one AOI and all data required the same bit depth.
Using the same acquisition using MultiPart at the C6 the format would look like this while still transmitting all date in one buffer not requiring any prostprocessing to extract the images:
Range Image 16 bpp
Intensity Image 10 bpp
Scatter Image 8 bpp
When now exchanging a C5 by a C6 in a existing system a whole change of the image acquisiton stack would be required and probably an update of the SDK version as well, bringing in multiple uncertainties.
Luckily the C6 offers a “backdoor” to be able to keep using GenICam 1.0 for the image acquisiton which also enables a relativly smooth transition when an exchange of a C5 to a C6 is required in a existing system.
For that the C6 offers the NodeMap parameter Cust::GevSCCFGMultiPart that allows to disable the MultiPart functinality and to use a GenICam 1.0 acquisiton mode, when disabled.
In this case the camera transmitts Range, Intensity and Scatter data of one AOI in a way that the Range data are transmitted in the so called image buffer while Intensity and Scatter are transmitted over image Chunk and can be read from the memory while both keep their own bit depth.
So for exchanging a C5 by C6 camera only requires to exchange the image extraction method after the identical image acquisiton method.
Here is an example how to change the extraction code for Range, Intensity and Scatter.
First the known way on extracting the three images from a C5 image in .NET:
public void ExtractInputImage()
{
//Data are transmitted in one single image of the size width * ProfilesPerFrame * 3 * 16 bpp. Alle three images are in 16 bpp.
RangeImage = new Image(InputImage.Width, NumberOfProfiles, 1, DataTypes.Int16BppUnsigned);
IntensityImage = new Image(InputImage.Width, NumberOfProfiles, 1, DataTypes.Int16BppUnsigned);
ScatterImage = new Image(InputImage.Width, NumberOfProfiles, 1, DataTypes.Int16BppUnsigned);
LinearAccessData<UInt16> imageDataInputImage = InputImage.Planes[0].GetLinearAccess<UInt16>();
LinearAccessData<UInt16> imageDataRangeImage = RangeImage.Planes[0].GetLinearAccess<UInt16>();
LinearAccessData<UInt16> imageDataIntensityImage = IntensityImage.Planes[0].GetLinearAccess<UInt16>();
LinearAccessData<UInt16> imageDataScatterImage = ScatterImage.Planes[0].GetLinearAccess<UInt16>();
for (int y = 0; y < NumberOfProfiles; y++)
{
for (int x = 0; x < InputImage.Width; x++)
{
//Iterate through input image by stepping every third line for each image type.
imageDataIntensityImage[x, y] = imageDataInputImage[x, y*3];
imageDataScatterImage[x, y] = imageDataInputImage[x, (y*3)+1];
imageDataRangeImage[x, y] = imageDataInputImage[x, (y*3)+2];
}
}
}
Now reaching the same goal with a C6. Remeber to deactivate MultiPart first:
BooleanNode Multipart = nmp["Cust::GevSCCFGMultiPart"] as BooleanNode;
Multipart.Value = false;
Now extract the Rangemap image from the raw input image and extract the Intensity and Scatter image from the attached chunk:
public void ExtractIntensityAndScatterFromImageChunk()
{
//Datatypes of images vary between Range, Intensity and Scatter.
RangeImage = InputImage; //Range image is transmitted in the image buffer of the datamessage.
IntensityImage = new Image(InputImage.Width, InputImage.Height, 1, DataTypes.Int10BppUnsigned);
ScatterImage = new Image(InputImage.Width, InputImage.Height, 1, DataTypes.Int8BppUnsigned);
LinearAccessData<UInt16> imageDataIntensityImage = IntensityImage.Planes[0].GetLinearAccess<UInt16>();
LinearAccessData<byte> imageDataScatterImage = ScatterImage.Planes[0].GetLinearAccess<byte>();
//Define the size of ChunkData
long ImageDataSize = InputImage.Width * InputImage.Height * 2;
long ChunkSize = PayloadSize - ImageDataSize;
unsafe
{
IntPtr ptrBaseIMG = InputImage.Planes[0].GetLinearAccess().BasePtr;//Get Basepointer of InputImage.
UInt16* ptrBaseIntensityImage = ((UInt16*)(ptrBaseIMG + (int)ImageDataSize))+4;//8 Byte Offset between Range Image and Intensity Image
byte* ptrBaseScatterImageOffset = ((byte*)(ptrBaseIMG + 2*(int)ImageDataSize))+16;//8 Byte Offset between Intensity Image and Scatter Image (+ Offset Range-Intensity)
//Iterate over memory staring at base pointer address, extracting Intensity and Scatter image.
for(int x = 0; x < InputImage.Width; x++)
{
for(int y = 0; y < InputImage.Height; y++)
{
UInt16* ptrCurrIntensityImage = (UInt16*)(ptrBaseIntensityImage + (x+(InputImage.Width * y)));
imageDataIntensityImage[x, y] = *ptrCurrIntensityImage;
byte* ptrCurrScatterImage = (byte*)(ptrBaseScatterImageOffset + (x+(InputImage.Width * y)));
imageDataScatterImage[x, y] = *ptrCurrScatterImage;
}
}
}
}
For further information on the usage of C5 cameras please refere to this forum post.
In the following posts there will be topics added related to the usage of C6 cameras in CVB.