ifm3d::Buffer- Basic C++ STL container for ifm3d
ifm3d::Buffer
is designed to provide a C++ STL container that can hold
buffer data of different types provided by ifm3d vision devices. Data is stored
in sequential memory layout and ifm3d::Buffer
provides a function template to access
the pixel. The pixel data type is defined in an enum ifm3d::pixel_format
.
ifm3d::Buffer
class does memory management and the user is free from the memory allocation
and deallocation. The assignment operator and the copy constructor
only copy the attributes and data is shared across the object.
Creating Buffer Object:
This can be done by calling ifm3d::Buffer()
and ifm3d::Buffer(rows, cols, nchannel, ifm3d::pixel_format)
.
The default Constructor only creates the attributes and the allocation of memory is
done on create(rows, cols, nchannel, ifm3d::pixel_format)
call.
ifm3d::Buffer::create(rows, cols, nchannel, ifm3d::pixel_format)
will allocate the required memory
only if the previous memory is not sufficient to store the buffer data.
//a 100 x 100 Buffer of type 8U
ifm3d::Buffer buffer;
buffer.create(100,100,1,ifm3d::FORMAT_8U)
//OR
//can also be created with parameter construction
ifm3d::Buffer buffer(100,100,1,ifm3d::FORMAT_8U);
//and now turn buffer to a 10 x10 3-channel 8-bit matrix.
// The old content will be deallocated
buffer.create(10,10,3,ifm3d::FORMAT_8U);
Accessing the Pixel
The ifm3d::Buffer
provides a template function to access data.
Use at<T>(index)
or at<T>(i,j)
to access the pixel. This functions returns the reference
to the pixel. A pixel is defined as a structure of n-channel values of type T at a given
index or position in 2D array.
// To access a pixel in ifm3d::Buffer I ( 100,100,1,ifm3d::FORMAT_8U) at 50,50
// position
auto pixel = I.at<uint8_t>(50,50);
// if working as Index array then
auto index = 50*100 + 50 ;
auto pixel = I.at<uint8_t>(index);
// Changing the pixel value can be done as follow :
// Writing 255 at pixel postion 50,50
I.at<uint8_t>(50,50) = 255;
I.at<uint8_t>(index) = 255;
To access a pixel in n-channel ifm3d::Buffer I ( 100,100,3,ifm3d::FORMAT_8U)
at
(50,50)
position, follow the example below (for a 3 channel Buffer),
as the pixel is a structure of the values of n-channel at a given position.
// User define struct
struct pixel{
uint8_t x;
uint8_t y;
uint8_t z;
}pixel_t;
// Accessing the value at 50, 50 position can be done as
auto pixel = I.at<pixel_t>(50,50);
auto x = pixel.x;
auto y = pixel.y;
auto z = pixel.z;
Buffer Templates
ifm3d::Buffer_<T>
extends ifm3d::Buffer
where T defines the data type in which the user wants to access the pixel.
This removes the need for providing the template type T while using the Buffer functionality
and working with std::algorithms.
Compatibility with C++ STL Algorithms
The ifm3d::Buffer
provides templated iterator to access data and to work with std::algorithms
.
The user can use ifm3d::IteratorAdapter<T>(ifm3d::Buffer)
which forwards type T to templated
iterators of the ifm3d::Buffer
.
ifm3d::Buffer buffer(10,10,1,ifm3d::FORMAT_16U);
for (auto value : ifm3d::IteratorAdapter<std::uint16_t>(buffer) )
{
// use value
}
// For multi channel buffer
ifm3d::Buffer buffer(10,10,3,ifm3d::FORMAT_16U);
for (auto value : ifm3d::IteratorAdapter<ifm3d::Point3D<uint16_t>>(buffer) )
{
std::cout << "(" << value.val[0] << ", " << value.val[1] << ", " << value.val[2] << ")" ;
}
The user can convert ifm3d::Buffer
to ifm3d::Buffer_<T>
, where T will define
the type in which the user wants to access the pixel. For ifm3d::Buffer_<T>
containers, the ifm3d::pixel_format
is deduced internally.
ifm3d::Buffer buffer(10,10,1,ifm3d::FORMAT_16U);
ifm3d::Buffer_<std::uint16_t> buffer_ = buffer;
for (auto value :buffer_ )
{
// use value
}
// For multi channel buffer
ifm3d::Buffer buffer(10,10,3,ifm3d::FORMAT_16U);
ifm3d::Buffer_<ifm3d::Point3D<uint16_t>> buffer_ = buffer;
for (auto value : buffer_ )
{
std::cout << "(" << value.val[0] << ", " << value.val[1] << ", " << value.val[2] << ")" ;
}
This way, ifm3d::Buffer
container can be used with any of the std::algorithm
Example grabbing distance and amplitude in ifm3d::Buffer
#include <iostream>
#include <ifm3d/device.h>
#include <ifm3d/fg.h>
#include <ifm3d/fg/buffer.h>
int main(int argc, const char** argv)
{
auto dev = ifm3d::Device::MakeShared();
uint16_t pcic_port = (dev->WhoAmI() == ifm3d::Device::device_family::O3R) ? 50012 : 50010;
auto fg = std::make_shared<ifm3d::FrameGrabber>(
dev, pcic_port); // 50012 for O3R use default value for other devices
fg->Start({ ifm3d::buffer_id::AMPLITUDE,ifm3d::buffer_id::XYZ, ifm3d::buffer_id::RADIAL_DISTANCE });
//polling the device
auto frame = fg->WaitForFrame().get();
ifm3d::Buffer amp_buffer = frame->GetBuffer(ifm3d::buffer_id::AMPLITUDE);
ifm3d::Buffer dist_buffer = frame->GetBuffer(ifm3d::buffer_id::RADIAL_DISTANCE);
// Accessing the pixels from ifm3d::Buffer
// Query the data format and channel.
std::cout << amp_buffer.nchannels() << std::endl;
std::cout << static_cast<int>(amp_buffer.dataFormat()) << std::endl;
// For O3D devices Amplitude and Distance data is `ifm3d::FORMAT_16U`
// whereas for O3X and O3R Device, the Amplitude buffer type is `ifm3d::FORMAT_32F`
// Refer to the section below for the full list of data types.
// With a 1 channel and float type buffer,
// the user can access data:
ifm3d::Buffer_<float> amp = amp_buffer;
for (auto& val : amp) {
//do something with val value
}
return 0;
}
Example grabbing XYZ or n-channel ifm3d::Buffer
#include <iostream>
#include <ifm3d/device.h>
#include <ifm3d/fg.h>
#include <ifm3d/fg/buffer.h>
int main(int argc, const char** argv)
{
auto dev = ifm3d::Device::MakeShared();
uint16_t pcic_port = (dev->WhoAmI() == ifm3d::Device::device_family::O3R) ? 50012 : 50010;
auto fg = std::make_shared<ifm3d::FrameGrabber>(
dev, pcic_port); // 50012 for O3R use default value for other devices
fg->Start({ ifm3d::buffer_id::AMPLITUDE,ifm3d::buffer_id::XYZ, ifm3d::buffer_id::RADIAL_DISTANCE });
//polling the device
auto frame = fg->WaitForFrame().get();
ifm3d::Buffer xyz = frame->GetBuffer(ifm3d::buffer_id::XYZ);
// Accessing the pixels from ifm3d::Buffer
// Query the data format and channel.
std::cout << xyz.nchannels() << std::endl;
std::cout << static_cast<int>(xyz.dataFormat()) << std::endl;
// For O3D devices XYZ data is`ifm3d::FORMAT_16S`
// whereas for O3X,O3R device XYZ buffer type is `ifm3d::FORMAT_32F
// Refer to the section below for the full list of data types.
// With 3 channel and float type
// using point3D_32F
ifm3d::Buffer_< ifm3d::Point3D_32F> xyz_data = xyz; // no copy of data
// With a range based `for` loop
for (const auto& point : xyz_data)
{
std::cout << "(" << point.val[1] << "," << point.val[2] << "," << point.val[0] << ")";
}
// With a pointer
for (int i = 0; i < xyz.height(); i++)
{
for (int j = 0; j < xyz.width(); j++)
{
auto ptr = xyz.ptr<float>(i, j);
auto z = ptr[0];
auto x = ptr[1];
auto y = ptr[2];
std::cout << "(" << x << "," << y << "," << z << ")";
}
}
return 0;
}
Device, Schema and data types for ifm3d::Buffer
ifm3d
supports multiple devices. These devices support multiple buffers/data types which can have different data formats on different devices.
The following table summarizes the buffers formats, along with their ifm3d::buffer_id, so a std::set<ifm3d::buffer_id>
needs to be pass in FrameGrabber::Start
method to enable the corresponding buffer for grabbing.
Data/Image |
ifm3d schema |
O3D3XX |
O3X |
O3R |
---|---|---|---|---|
Radial distance image |
ifm3d::buffer_id::RADIAL_DISTANCE |
std::uint16_t |
float |
float |
Amplitude image |
ifm3d::buffer_id::AMPLITUDE |
std::uint16_t |
float |
float |
Raw amplitude image |
ifm3d::buffer_id::RAW_AMPLITUDE |
std::uint16_t |
float |
NA |
Cartesian coordinate |
ifm3d::buffer_id::XYZ |
std::int16_t |
float |
float |
Unit vector |
ifm3d::buffer_id::UNIT_VECTOR_ALL |
float |
float |
NA |
Image grayscale |
ifm3d::buffer_id::GRAY |
std::uint16_t |
float |
NA |
Distance Noise Image |
ifm3d::buffer_id::DISTANCE_NOISE |
NA |
std::uint16_t |
std::uint16_t |
Confidence Image |
ifm3d::buffer_id::CONFIDENCE |
std::uint8_t |
std::uint8_t |
std::unit16_t |
JPEG |
ifm3d::buffer_id::IMG_JPEG |
NA |
NA |
std::unit8_t |
Along with above data ifm3d also supports ifm3d::buffer_id values, which is used to obtain data that are obtained in standard STL containers or C++ default types.
Data/Image |
ifm3d schema |
O3D3XX |
O3X |
O3R |
---|---|---|---|---|
JSON Model Data |
ifm3d::buffer_id::JSON_MODEL |
std::string |
NA |
NA |
JSON Model Data |
ifm3d::buffer_id::JSON_MODEL |
std::string |
NA |
NA |
Intrinsic calibration parameter |
ifm3d::buffer_id::INTRINSIC_CALIBRATION |
std::vector |
NA |
std::vector |
inverse Intrinsic calibration parameter |
ifm3d::buffer_id::INVERSE_INTRINSIC_CALIBRATION |
std::vector |
NA |
std::vector |
Illumination temperature |
ifm3d::buffer_id::ILLUMINATION_TEMP |
float |
NA |
NA |
Exposure time |
ifm3d::buffer_id::EXPOSURE_TIME |
std::vector<ifm3d::TimePointT> |
std::vector<ifm3d::TimePointT> |
std::vector<ifm3d::TimePointT> |