Hi, I found the source code for C++ of accessing data from multi stream camera. (https://help.commonvisionblox.com/NextGen/14.0/md_theory_of_operation_image_manager__migration_guide__acquisition_stack.html). I am working in python. How can I use this code in python for multi-stream case? I can do for single stream.
#include <iostream>
#include <chrono>
#include <algorithm>
#include <cvb/device_factory.hpp>
#include <cvb/image.hpp>
#include <cvb/global.hpp>
// constants
static const constexpr auto TIMEOUT = std::chrono::milliseconds(3000);
static const constexpr int NUM_ELEMENTS_TO_ACQUIRE = 10;
void PrintOutAllPartTypes(const Cvb::MultiPartImage& multiPartImage);
static std::map<Cvb::WaitStatus, const char*>
WAIT_ERROR_STATES
{
{Cvb::WaitStatus::Timeout, "timeout"},
{Cvb::WaitStatus::Abort, "abort"}
};
int main()
{
try
{
// discover transport layers
auto infoList = Cvb::DeviceFactory::Discover(Cvb::DiscoverFlags::IgnoreVins);
// can't continue the demo if there's no available device:
if (infoList.empty())
throw std::runtime_error("There is no available device for this demonstration.");
// instantiate the first device in the discovered list
auto device = Cvb::DeviceFactory::Open(infoList[0].AccessToken(), Cvb::AcquisitionStack::GenTL);
// Get all streams
std::vector<Cvb::ImageStreamPtr> streams;
std::generate_n(std::back_inserter(streams), device->StreamCount(), [&device, i = 0]() mutable
{
return device->Stream<Cvb::ImageStream>(i++);
});
// start the data acquisition for all streams
for (const auto stream : streams)
{
stream->Start();
}
// acquire data
// note: getting the data is sequential here for simplicity;
// concurrent wait on different streams is the more likely use case
for (auto index = 0; index < NUM_ELEMENTS_TO_ACQUIRE; ++index)
{
for (auto streamIndex = 0u; streamIndex < streams.size(); ++streamIndex)
{
const auto stream = streams[streamIndex];
Cvb::MultiPartImagePtr multiPartImage;
Cvb::WaitStatus waitStatus;
Cvb::NodeMapEnumerator enumerator;
std::tie(multiPartImage, waitStatus, enumerator) = stream->WaitFor(TIMEOUT);
switch (waitStatus)
{
default:
std::cout << "unknown wait status\n";
case Cvb::WaitStatus::Abort:
case Cvb::WaitStatus::Timeout:
{
std::cout << "wait status not ok: " << WAIT_ERROR_STATES[waitStatus] << "\n";;
continue;
}
case Cvb::WaitStatus::Ok: break;
}
PrintOutAllPartTypes(*multiPartImage);
auto element1 = multiPartImage->GetPartAt(0);
if (!Cvb::holds_alternative<Cvb::ImagePtr>(element1))
{
std::cout << "multi part image does not contain an image as first element\n";
continue;
}
auto image = Cvb::get<Cvb::ImagePtr>(element1);
auto linearAccess = image->Plane(0).LinearAccess();
std::cout << "Acquired image: #" << index + 1 << ", at address " << linearAccess.BasePtr() << " from stream " << streamIndex << "\n";
}
}
// synchronous stop
for (const auto stream : streams)
{
stream->Stop();
}
}
catch (const std::exception& error)
{
std::cout << error.what() << std::endl;
}
return 0;
}
void PrintOutAllPartTypes(const Cvb::MultiPartImage& multiPartImage)
{
const auto numParts = multiPartImage.NumParts();
for (auto partIndex = 0; partIndex < numParts; ++partIndex)
{
const auto part = multiPartImage.GetPartAt(partIndex);
std::cout << "part ";
if (Cvb::holds_alternative<Cvb::ImagePtr>(part))
std::cout << part.index() + 1 << " of " << numParts << " is an image\n";
if (Cvb::holds_alternative<Cvb::PlanePtr>(part))
std::cout << part.index() + 1 << " is a plane\n";
if (Cvb::holds_alternative<Cvb::PlaneEnumeratorPtr>(part))
std::cout << part.index() + 1 << " is a plane enumerator\n";
if (Cvb::holds_alternative<Cvb::BufferPtr>(part))
std::cout << part.index() + 1 << " is a buffer\n";
if (Cvb::holds_alternative<Cvb::PFNCBufferPtr>(part))
std::cout << part.index() + 1 << " is a pfnc buffer\n";
}
}