1. Project Architecture¶
First of all, this is mainly a project written in C language. There are some exceptions with some part of the code written in C++ but the C++ code is not mandatory and the project can always compile with a C compiler.
Thus, this projects can be seen as a pool of C structures and C functions.
The headers are located in the ./include/c/fmdt
folder (= structures,
enumerations, defines and functions declarations). And the implementations of
the functions are located in the ./src/common
folder.
1.1. Modules¶
Headers (.h
files) and function implementations (.c
files) are grouped
into modules. A module is a set of headers and implementation files that
are working on the same “topic”. For instance, a k-NN module has been
implemented is the project. It is composed of the following files:
./include/c/fmdt/kNN.h
: this is a proxy header file that includeskNN_struct.h
,kNN_compute.h
andkNN_io.h
headers,./include/c/fmdt/kNN/kNN_struct.h
: contains structure definitions related to k-NN,./include/c/fmdt/kNN/kNN_compute.h
: declares the functions related to k-NN computations,./include/c/fmdt/kNN/kNN_io.h
: declares the functions related to k-NN inputs and outputs, in the case of the k-NN matching there are only functions to display the output results after the computations,./src/common/kNN/kNN_compute.c
: implementations of the functions declared in thekNN_compute.h
file, plus additional private functions,./src/common/kNN/kNN_io.c
: implementations of the functions declared in thekNN_io.h
file, plus additional private functions.
This decomposition in several files is made to have a good separation of concerns. This way developers can easily know what to find in each file.
1.2. Executables¶
The source code of the final executables is located in ./src/mains/
directory. Each file corresponds to a final executable and thus contains a
main
function.
1.3. Public Interfaces¶
Generally there are two levels to call a processing function. For instance, in
the k-NN module and in the kNN_compute.h
header, the two following
functions are defined:
void _kNN_match(float** data_distances, uint32_t** data_nearest, uint32_t* data_conflicts, const uint32_t* RoIs0_id,
const uint32_t* RoIs0_S, const float* RoIs0_x, const float* RoIs0_y, uint32_t* RoIs0_next_id,
const size_t n_RoIs0, const uint32_t* RoIs1_id, const uint32_t* RoIs1_S, const float* RoIs1_x,
const float* RoIs1_y, uint32_t* RoIs1_prev_id, const size_t n_RoIs1, const int k,
const uint32_t max_dist, const float min_ratio_S);
void kNN_match(kNN_data_t* kNN_data, const RoIs_basic_t* RoIs0_basic, const RoIs_basic_t* RoIs1_basic,
RoIs_asso_t* RoIs0_asso, RoIs_asso_t* RoIs1_asso, const int k, const uint32_t max_dist,
const float min_ratio_S);
Both functions compute the k-NN matching. The function prefixed with an
underscore (_kNN_match
) requires only buffers of native types (float
and
uint32_t
here) while the other function (kNN_match
) requires structure
types (kNN_data_t
, RoIs_basic_t
and RoIs_asso_t
). In the
implementation, the kNN_match
function simply call the _kNN_match
function.
Compute functions often use inner data. This data is NOT input or output data.
This is data required to store intermediate results during the computation.
They are different ways to manage this type of data in C codes. In FMDT the
chosen pattern is to allocate this inner data before calling the compute
function. And to deallocate this data after. For instance, in the previous
kNN_match
function, the first parameter is a pointer of kNN_data_t
type.
This data can be allocated with the kNN_alloc_data
function defined in the
same kNN_compute.h
header.
The following lines illustrate how to properly use the k-NN module:
// inner data allocation on the heap
kNN_data_t* kNN_data = kNN_alloc_data(MAX_SIZE);
// initialization of the data with zeros (this is NOT mandatory)
kNN_init_data(kNN_data);
// kNN matching computation (multiple calls of kNN match function with the same `kNN_data`)
kNN_match(kNN_data, /* ... */);
kNN_match(kNN_data, /* ... */);
kNN_match(kNN_data, /* ... */);
kNN_match(kNN_data, /* ... */);
// inner data deallocation
kNN_free_data(kNN_data);
1.4. Dependencies¶
FMDT depends on multiple external libraries to work. The following section details each of these libraries.
1.4.1. ffmpeg-io¶
ffmpeg-io is a wrapper for the ffmpeg
executable. In FMDT, this library
is used in the video
module (to read/write videos/images).
Note
ffmpeg-io requires the installation of the ffmpeg
executable to
work. The library mainly exchanges data with ffmpeg
through system
pipes.
1.4.2. NRC¶
NRC is a library dedicated to 1D and multidimensional efficient memory allocations. This library is used everywhere data allocation are needed.
1.4.3. C Vector¶
C Vector in a library that implements dynamic arrays like std::vector
in
C++. This is useful when we cannot predict in advance the size of a buffer.
For instance, in FMDT, a C Vector is used to store the final tracks.
1.4.4. AFF3CT-core¶
AFF3CT-core is a library that includes a multi-threaded runtime. In FMDT,
this multi-threaded runtime is used to speed the restitution time of the
final executables. For instance, the ./src/detect_rt.cpp
is feature
compliant with ./src/detect.cpp
. The main difference is that
./src/detect_rt.cpp
is multi-threaded with the AFF3CT-core library.
Note
AFF3CT-core is a C++ library. When FMDT is linked with AFF3CT-core, then the code requires a C++ compiler to be compiled.
1.4.5. OpenCV¶
OpenCV is a famous library dedicated to a large set of computer vision algorithms. In FMDT, OpenCV is mainly used to write text in images.
Note
OpenCV is a C++ library. When FMDT is linked with OpenCV, then the code requires a C++ compiler to be compiled.