Multi Part Image

<< Click to Display Table of Contents >>

Navigation:  Migration Guide for the Acquisition Stacks > CVB++ >

Multi Part Image

Multi part basically means that the stream returns a composite instead of an image which may itself consist of one or more image(s), planes of point cloud(s) etc. In other words: A composite is a way to iterate over and interpret the delivered data and it will in fact be necessary to do so in order to make sense of the acquired data.

The use of a composite element's data is represented by the composite purpose, which can be:

Custom: an unspecified custom composite - consult the source of the image for an interpretation.

Image: one image, potentially with extra data.

ImageList: multiple images grouped together.

MultiAoi: multiple images that represent multiple AOIs in one frame.

RangeMap: a 2.5D image, potentially with extra data.

PointCloud: 3D data, potentially with extra data.

ImageCube: a (hyper spectral) image cube.

The different part types are:

A standard image

A single plane of data holding, e.g for point clouds confidence data

A collection of grouped planes, e.g. R,G and B planes

A generic raw buffer

A raw buffer following Pixel Format Naming Convention (PFNC) for e.g. packed data, which is not representable as an image.

 

Code Examples

There are multiple ways to check for multi part images. One possibility is to check the incoming composite's elements for image data:

3rd generation stack

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

auto devices = DeviceFactory::Discover(DiscoverFlags::IgnoreVins);

auto device = DeviceFactory::Open<GenICamDevice>(devices[0].AccessToken(),

 AcquisitionStack::GenTL);

auto stream = device->Stream<CompositeStream>();

stream->Start();

for (int i = 0; i < 10; ++i)

{

auto [composite, status, nodeMaps] = stream->Wait();

 auto numElements = composite->ItemCount();

 if (numElements < 2)

  return; // no multi part

 for (auto j = 0; j < numElements; j++)

 {

  auto element = composite->ItemAt(j);

  if (!holds_alternative<ImagePtr>(element))

   {

    auto image = get<ImagePtr>(element);

   }

  else

    std::cout << "Element is not an image\n";

 }

}

stream->Abort();

(9) Extract the number of elements.

(14) Get each element from this composite.

(15) Verify the element's type using the holds_alternative function.

 

An alternative approach would be to build a MultiPartImage object from the composite:

3rd generation stack

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

auto devices = DeviceFactory::Discover(DiscoverFlags::IgnoreVins);

auto device = DeviceFactory::Open<GenICamDevice>(devices[0].AccessToken(),

 AcquisitionStack::GenTL);

auto stream = device->Stream<CompositeStream>();

stream->Start();

for (int i = 0; i < 10; ++i)

{

auto [composite, status, nodeMaps] = stream->Wait();

 auto multiPartImage = MultiPartImage::FromComposite(composite);

 auto numParts = multiPartImage->NumParts();

 for (auto j = 0; j < numParts; j++)

 {

  auto element = multiPartImage->GetPartAt(j);

  if (!holds_alternative<ImagePtr>(element))

   {

    auto image = get<ImagePtr>(element);

   }

  else

    std::cout << "Element is not an image\n";

 }

}

stream->Abort();

(9) Converting the composite to a MultiPartImage will make will make the image data accessible. Please note that the device needs to deliver at least one composite elements that may be interpreted as a CVB image for this approach to be viable.

(10) Retrieve the number of parts within this multi part image.

(13) Get the element from the multi part image.

(14) The type of this element can be verified by the holds_alternative function.

 

1

2

3

4

5

6

7

8

9

10

if (holds_alternative<ImagePtr>(part))

std::cout << part.index() + 1 << " is an image\n";

if (holds_alternative<PlanePtr>(part))

std::cout << part.index() + 1 << " is a plane\n";

if (holds_alternative<PlaneEnumeratorPtr>(part))

std::cout << part.index() + 1 << " is a plane enumerator\n";

if (holds_alternative<BufferPtr>(part))

std::cout << part.index() + 1 << " is a buffer\n";

if (holds_alternative<PFNCBufferPtr>(part))

std::cout << part.index() + 1 << " is a pfnc buffer\n";

 

Summary

As has been shown, acquiring multi part data from a camera is not actually any more complex than acquiring a composite - the actual effort with multi part data goes into parsing the content of the received composite. Usually this will be done with the properties of the hardware in mind, i.e. like in the example above, the code usually contains assumptions about the content of the composite (that should, of course, be verified) and therefore tends to be somewhat device-specific.