# Camera API The Camera API is a low level API built on top of the different vendor SDKs and provides a uniform interface to the camera configuration and frame acquisition. A Camera Plugin is an implementation of this interface built on top of the various vendor SDKs. ## Synopsis ```c++ class camera { // Define the supported image types (a vector of types) typedef ... images_t; // Define the type of the initialization parameters typedef ... init_params_t; // Define the type of the acquisition parameters typedef ... acq_params_t; // Returns the description of the layout layout_t get_layout(); // Control part of the camera struct control { // Initialize the camera void control(const init_params_t& params); // Introspect the capabilities of the camera template std::optional get_capability(); // Prepare the camera for acquisition void prepare(const acq_params_t& params); // Start the acquisition void start(); // Software trigger if the camera supports it void trigger(); // Stop the acquisition void stop(); // Returns the effective acquisition parameters acq_params_t acq_params() const; }; // Acquisition part of the camera struct acquisition { // Initialize the camera void acquisition(const init_params_t& params); // Returns an allocator associated with the buffers allocator_t get_allocator(); #if !defined(LIMA_IS_MULTI_DATA_CHANNELS) // Returns a newly acquired set of images // \warning this call might block and should be called asynchronously images_t get_images(); #else // Returns a newly acquired set of images for a given data channel // \warning this call might block and should be called asynchronously images_t get_images(int channel = 0); // Returns the number of data channels int nb_channels() const; #endif // !defined(LIMA_IS_MULTI_DATA_CHANNELS) }; }; ``` ## State machine Because different camera SDKs require different steps to the implement the transition from one state to another (e.g. prepared -> running), the FSM's actions are fully overridable. TODO ## Detector modules layout A detector layout is composed of modular items. Each item can be rotated and/or flipped due to detector readout electronics design. In such cases, the isometric transformation necessary to reconstruct the data in the final layout must be defined. See :doc:`geometry_transformations`. Further operations can be performed on the full layout, affecting all the items. One specific operation is image crop (RoI), which may result in the exclusion of one or more items from the layout. Those "not-in-layout" items are nevertheless referenced by the layout structure in order to not change the item index list. The layout is just a description of how the modular items are arranged. In order to assemble the final image the source data must be provided. The implementation expects one source view per layout item, even "not-in-layout" items. An affine matrix transforming from sensor coordinates to final image coordinates is kept by the layout. This is useful when the user wants to keep the same region-of-interest in the sensor while adding/removing geometric transformations. ``` c++ struct layout_item { // Position in the destination point_t dst_topleft; // Selection within the source point_t src_topleft; point_t src_dimensions; // Transformation to be applied on item to reconstruct the layout any_isometric_xform_t xform; // default is none bool in_layout() const; image_rect get_src_bounding_box() const; image_rect get_dst_bounding_box() const; point_t get_dst_dimensions() const; }; // A layout is basically a container of items struct layout { // Add/retreive a layout item void add_item(layout_item i); const layout_item& get_item(int i) const; std::size_t size() const; // Return/set the dimension of the full image const point_t& get_dims() const; void set_dims(point_t dims); // converts sensor pixel coordinates into layout coordinates affine_t get_sensor_coordinates_matrix() const; ... }; ``` ### Transformation The layout implements the following transformations: ```c++ // Image algorithms void vert_flip(); void horz_flip(); void rotate90cw(); void rotate90ccw(); void rotate180(); void crop(point_t topleft, point_t dimensions); ``` Each transformation updates the item state as well as the layout dimensions and the sensor-coordinates-matrix. See :doc:`geometry_transformations`. ### Reconstruction The layout reconstruction can be performed in two variants * Memory. This implementation uses serial Boost.Gil algorithms to reconstruct the layout items into a single image: ``` c++ // Reconstruction to memory template void assemble(const Range& views, Image& out, Value fillvalue) const; ``` * Virtual data set: TODO ``` c++ // Reconstruction to file template void generate_vds(const std::string& filename, Range h5_sources, T fillvalue) const; ``` ## Usage #### Camera construction ```c++ // Set the initialization parameters camera::init_params_t init_params; init.ip = "127.0.0.1"; init.port = 80; // Construct the camera camera cam(init_params); ``` ```c++ // Or construct the camera directly with initialization list camera cam({"127.0.0.1", 8080}); ``` ### Acquisition ```c++ // Set the acquisition parameters camera::acq_params_t acq_params; acq.shutter_speed = 5; acq.binning = {2, 2}; cam.prepare(acq_params); cam.start(); for (int i : ) ``` ## Implementation ### CRTP Delegates part of the implementation to the base class. ``` c++ class config { // Define the supported image types (a vector of types) typedef ... images_t; // Define the type of the initialization parameters typedef ... init_params_t; // Define the type of the acquisition parameters typedef ... acq_params_t; }; class camera : lima::camera { } ``` ### Reflection / Introspection Use reflection for parameters so that serialization and visitation could be generated. with [Boost.Hana](http://boostorg.github.io/hana): ```cpp struct init_params { BOOST_HANA_DEFINE_STRUCT(Person, (std::string, ip), (int, port) ); }; using namespace hana = boost::hana; hana::for_each(john, [](auto pair) { std::cout << hana::to(hana::first(pair)) << ": " << hana::second(pair) << std::endl; }); ``` with [Boost.PFR](http://apolukhin.github.io/magic_get/index.html): ```c++ struct init_params { BOOST_HANA_DEFINE_STRUCT(Person, (std::string, ip), (int, port) ); }; init_params params; boost::pfr::for_each_field(params, [](const auto& field, std::size_t idx) { std::cout << idx << ": " << boost::typeindex::type_id_runtime(field) << '\n'; }); ``` ### External acquisition loop