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 enumeration 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;
}