This lib can be used to generate arbitrary bezier functions (e.g. for free form deformations). The function generation is static (happens at compile time). The end result is an optimized function.
The bezier function template is a variadic. It expects a list of integers, which defines the bernstein polynomials used in the generated bezier function.
bezier<x, y, z, ...>(in_position, in_control_points)
The number of template parameters also defines the dimension of the control point array in_control_points. If you work with images, you will have two template parameters and a 2D control point array. If you work with 3D meshes, you will have three template parameters and a 3D control point array. The value of the template parameters x, y, z, .. is the number of control points per dimension (row, column, ..) in in_control_points.
The function itself expects two input parameters
in_position: A vector with dimension equal to the number of template parameters (e.g. glm::vec, or an vector/array type). The values of the vector must be within 0 < x < 1.
in_control_points: A control point array (with a dimension equal to the number of template parameters) holding vectors with a dimension equal to the number of template parameters
The function returns a vector with dimension equal to the input.
The library itself requires C++17. The demos Qt5, QtQuick and Qt3D.
cd StaticBezier
mkdir build
cmake ..
make
All demos are included as subfolders within the project's root directory.
Small demo to perform a free form deformation on an image. Note that the black lines in the output are just resampling artifacts.
int w = img.width();
int h = img.height();
std::map<std::array<float, 2>, QRgb> transf_img_arr;
std::array<glm::vec2, 3> a1 = { glm::vec2(0.0, 0.0), glm::vec2(0.0, 0.5), glm::vec2(0.0, 1.0) };
std::array<glm::vec2, 3> a2 = { glm::vec2(0.5, 0.0), glm::vec2(0.5, 0.5), glm::vec2(0.5, 1.4) };
std::array<glm::vec2, 3> a3 = { glm::vec2(0.9, 0.0), glm::vec2(1.0, 0.5), glm::vec2(1.0, 1.0) };
std::array<std::array<glm::vec2, 3>, 3> ctrl2d = { a1, a2, a3 };
// scaling, ffd, boundary estimation
float mx(-FLT_MAX), my(-FLT_MAX);
for(int i = 0; i < w; i++)
for(int j = 0; j < h; j++) {
glm::vec2 t = bezier<3,3>(glm::vec2((float)i/w, (float)j/h), ctrl2d) * glm::vec2(w, h);
transf_img_arr[{t.x, t.y}] = img.pixel(i, j);
mx = mx < t.x ? t.x : mx;
my = my < t.y ? t.y : my;
}
Image Before | Image After |
---|---|
The demo shows how to use the template to generate a function for a 3x3x3 control point grid to deform 3D-meshes.
Mesh Before FFD | Mesh After FFD |
---|---|