Hello all,
I am working with Jai SW4000Q line scan camera. This camera gives both RGB and NIR images. Previously I was accessing both the images as two separate streams (DS0 and DS1). Now, I would like to combine all 4 planes into one stream and read the image with 4 planes in a single stream output. I know this is possible with setting the pixel format to RGBa8 as given in the manual (image attached below).
Using genicam browser, when I set the pixel format to “RGBa8”, I can see that the amount of data received from the camera goes from 800 to 1000 MB/sec which indicates that there are 4 planes in the image.
I tried to do the same thing using CVB++ using the below code
#include <cvb/device_factory.hpp>
#include <cvb/utilities/system_info.hpp>
#include <cvb/driver/stream.hpp>
#include <cvb/global.hpp>
#include <cvb/driver/composite_stream.hpp>
#include <cvb/genapi/node_map_enumerator.hpp>
#include <cvb/driver/image_rect.hpp>
#include<chrono>
#include <time.h>
#include <stdlib.h>
#include <thread>
#include <memory>
#include<filesystem>
#include<cmath>
#define ACQUISITION_TIME 10
#define MAC_ID_LINE_SCAN "00-0C-DF-0A-6B-6F"
#define LINE_SCAN_DRIVER_TYPE "FILTER" // "FILTER" or "SOCKET"
using namespace Cvb;
using namespace std::chrono;
static std::map<Cvb::WaitStatus, const char*>
WAIT_ERROR_STATES
{
{Cvb::WaitStatus::Timeout, "timeout"},
{Cvb::WaitStatus::Abort, "abort"}
};
void SetIntegerNodeMapValue(Cvb::GenApi::IntegerNodePtr fromNode, int toValue) {
fromNode->SetValue(toValue);
std::cout << "Set " << fromNode->Name() << " to value: " << fromNode->Value() << std::endl;
}
void SetFloatNodeMapValue(Cvb::GenApi::FloatNodePtr fromNode, float toValue) {
fromNode->SetValue(toValue);
std::cout << "Set " << fromNode->Name() << " to value: " << fromNode->Value() << std::endl;
}
void SetFEnumNodeMapValue(Cvb::GenApi::EnumerationNodePtr fromNode, std::string toValue) {
fromNode->SetValue(toValue);
std::cout << "Set " << fromNode->Name() << " to value: " << fromNode->Value() << std::endl;
}
int main(int argc, char* argv[])
{
std::string json_config_path;
std::string save_directory_path_RGB, save_directory_path_NIR;
json_config_path = argv[1];
LineScanConfig line_scan_config;
line_scan_config = parse_json(json_config_path);
try
{
auto path = Cvb::InstallPath();
path += CVB_LIT("drivers\\GenICam.vin");
std::cout<<"GeniCam Driver Path : "<<path<<std::endl;
auto flags = Cvb::DiscoverFlags::IgnoreVins | Cvb::DiscoverFlags::IgnoreGevSD;
//const auto timeout = std::chrono::seconds(2);
auto discovery_tokens = Cvb::DeviceFactory::Discover(flags);
std::cout<<"Number of Devices Discovered :"<<discovery_tokens.size()<<std::endl;
std::cout<<"Type of Discovery Tokens : "<<typeid(discovery_tokens).name()<<std::endl;
unsigned int device_index = 0;
for(auto &token : discovery_tokens)
{
std::string device_mac, interface_driver;
if(token.TryGetProperty(Cvb::DiscoveryProperties::DeviceMac, device_mac) && \
token.TryGetProperty(Cvb::DiscoveryProperties::InterfaceDriverType , interface_driver) )
{
std::cout<<"Found device MAC and Interface Driver : "<< device_mac<< " : " <<interface_driver<<std::endl;
std::cout<<"Device Index : "<<device_index<<std::endl;
}
if(!device_mac.compare(MAC_ID_LINE_SCAN) && ! interface_driver.compare(LINE_SCAN_DRIVER_TYPE))
{
std::cout<<"Opening Device : " << device_mac << " using "<<interface_driver<<" driver"<<std::endl;
//token.SetParameter("PixelFormat", "0");
//token.SetParameter("NumBuffer", "50");
break;
}
device_index++;
}
auto line_scan_device = Cvb::DeviceFactory::Open(discovery_tokens[device_index].AccessToken(), Cvb::AcquisitionStack::GenTL);
auto device_node_map = line_scan_device->NodeMap(CVB_LIT("Device"));
auto old_width = device_node_map->Node<IntegerNode>("Std::Width");
auto old_height = device_node_map->Node<IntegerNode>("Std::Height");
auto frame_rate = device_node_map->Node<FloatNode>("Std::AcquisitionFrameRate");
auto pixelFormat = device_node_map->Node<EnumerationNode>("Std::PixelFormat");
auto componentSelector = device_node_map->Node<EnumerationNode>("Std::ComponentSelector");
auto line_rate = device_node_map->Node<FloatNode>("Std::AcquisitionLineRate");
SetIntegerNodeMapValue(device_node_map->Node<IntegerNode>("Std::Width"), line_scan_config.Parameters.image_width);
SetIntegerNodeMapValue(device_node_map->Node<IntegerNode>("Std::Height"), line_scan_config.Parameters.image_height);
SetFEnumNodeMapValue(device_node_map->Node<EnumerationNode>("Std::PixelFormat"),"RGBa8");
auto set_width = device_node_map->Node<IntegerNode>("Std::Width");
auto set_height = device_node_map->Node<IntegerNode>("Std::Height");
std::cout<<"Set Width : " <<set_width->Value() <<std::endl;
std::cout<<"Set Height : " <<set_height->Value() <<std::endl;
std::cout<<"Changed Frame Rate : "<<device_node_map->Node<FloatNode>("Std::AcquisitionFrameRate")->Value()<<std::endl;
std::cout<<"Changed Pixel Format : "<<device_node_map->Node<EnumerationNode>("Std::PixelFormat")->Value()<<std::endl;
auto image_stream = line_scan_device->Stream<Cvb::ImageStream>(0);
image_stream->Start();
auto start = high_resolution_clock::now();
static const constexpr auto TIMEOUT = std::chrono::milliseconds(3000);
unsigned int i = 0;
while(duration_cast<seconds>(high_resolution_clock::now() - start).count() < ACQUISITION_TIME)
{
Cvb::MultiPartImagePtr multiPartImage;
Cvb::WaitStatus waitStatus;
Cvb::NodeMapEnumerator enumerator;
std::tie(multiPartImage, waitStatus, enumerator) = image_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;
}
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<<"Number of Planes in the image : " <<image->PlanesCount() <<std::endl;
std::cout << "Acquired image: #" << i << ", at address " << linearAccess.BasePtr() << "\n";
i ++ ;
}
image_stream->Stop();
}
catch(const std::exception& error)
{
std::cout<<" Camera config : "<<error.what()<<std::endl;
}
return 0;
}
Now, using the above code I tried to print out the number of planes received by the image and it says 3 instead of 4. Is there a way to get all 4 planes in a single output stream ?