# 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```](../../../modules/device/include/ifm3d/device/device.h#L69). ```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. ```cpp //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(index)` or `at(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. ```cpp // To access a pixel in ifm3d::Buffer I ( 100,100,1,ifm3d::FORMAT_8U) at 50,50 // position auto pixel = I.at(50,50); // if working as Index array then auto index = 50*100 + 50 ; auto pixel = I.at(index); // Changing the pixel value can be done as follow : // Writing 255 at pixel postion 50,50 I.at(50,50) = 255; I.at(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. ```cpp // 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(50,50); auto x = pixel.x; auto y = pixel.y; auto z = pixel.z; ``` ## Buffer Templates ```ifm3d::Buffer_``` 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(ifm3d::Buffer)``` which forwards type T to templated iterators of the ```ifm3d::Buffer```. ```cpp ifm3d::Buffer buffer(10,10,1,ifm3d::FORMAT_16U); for (auto value : ifm3d::IteratorAdapter(buffer) ) { // use value } // For multi channel buffer ifm3d::Buffer buffer(10,10,3,ifm3d::FORMAT_16U); for (auto value : ifm3d::IteratorAdapter>(buffer) ) { std::cout << "(" << value.val[0] << ", " << value.val[1] << ", " << value.val[2] << ")" ; } ``` The user can convert ```ifm3d::Buffer``` to ```ifm3d::Buffer_```, where T will define the type in which the user wants to access the pixel. For ```ifm3d::Buffer_``` containers, the [ifm3d::pixel_format](../../../modules/device/include/ifm3d/device/device.h#L69) is deduced internally. ```cpp ifm3d::Buffer buffer(10,10,1,ifm3d::FORMAT_16U); ifm3d::Buffer_ buffer_ = buffer; for (auto value :buffer_ ) { // use value } // For multi channel buffer ifm3d::Buffer buffer(10,10,3,ifm3d::FORMAT_16U); ifm3d::Buffer_> 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 ```cpp #include #include #include #include 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( 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(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_ amp = amp_buffer; for (auto& val : amp) { //do something with val value } return 0; } ``` ## Example grabbing XYZ or n-channel ifm3d::Buffer ```cpp #include #include #include #include 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( 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(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(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](../../../modules/framegrabber/include/ifm3d/fg#L22), so a ```std::set``` 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](../../../modules/framegrabber/include/ifm3d/fg#L22) 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\ | std::vector\ | std::vector\ |