Welcome to follow the public account: Sumsmile/focus on image processing mobile development veteran ~~

This article is about the principle of Bezier curve and code implementation, a very simple and easy one.

background

Geometric modeling and simulation is a very important module in graphics. In practical application scenarios, the appearance of models is often irregular and cannot be generated by simple points, lines and planes.

Bessel curves are simple and practical geometric models. [Video can not be played on the nuggets, please preview in the “Sumsmile” public account] Graphics rendering (4) Bezier curve

The Bezier curve was widely published in 1962 by French engineer Pierre Bezier, who used it to design the body of a car. Wikipedia-bezier curve

It can be seen that industry promotes scientific civilization

Bezier curve principle

Derivation of curve principle

The principle is very simple, follow my thinking step by step derivation.

  1. I can take a point on the line P0, P1

  1. Two points are taken on P0P1 and P1P2 respectively according to the ratio T to form a line (green), and another point (black) is taken on the green line according to the ratio T, and then the value of T is constantly changed [0~1]. The red line formed by the continuous movement of black points is the quadratic Bessel curve.

You should get a sense of it. This is a classic recursive algorithm.

Understand the quadratic Bezier curve, and then feel the evolution of the higher order.

  • Three bezier curves

  • Four Bezier curves

  • Five Bezier curves

Derivation of mathematical formula

As mentioned above, Bessel curves are controlled by multiple points. You take the points on the line segment in turn by scaling t, and then you take the points, and then you take the points, and then you leave only one point, which is the trajectory of the Bezier curve.

Take the conic as an example:

It looks like the coordinates of b0, B1 and B2 are evaluated by weight.

What if it’s multiples? In fact, the coefficients at each point follow the rules of quadratic polynomials.

If I have n points, then the path of the curve is determined by this algebraic formula, which I won’t go into, but I’ll just have to be patient.

Of course, computer programs don’t have to go through so much algebra, they just iterate.

Bessel curve code implementation

Implementation code,

Based on openCV, select 4 points on the screen to generate a Bezier curve.

The code has detailed comments, compared to the comments to see the code. Detailed codes are appended at the end of the paper.

/** * Bessel curve recursive algorithm, calculate each T on a curve locus points ** control_points: control Bessel curve points * T: interpolation ratio/weight */
cv::Point2f recursive_bezier(const std::vector<cv::Point2f> &control_points, float t) 
{

    if (control_points.size() = =1) {
        return control_points[0];
    }

    std::vector<cv::Point2f> lerp_points;
    for (size_t i = 1; i < control_points.size(a); i++) { lerp_points.push_back(lerp_v2f(control_points[i - 1], control_points[i], t));
    }
    
    return recursive_bezier(lerp_points, t);

}

/** * trigger Bezier curve interpolation algorithm, get all points ** control_points: control bezier curve points ** window: draw a curve/point window */
void bezier(const std::vector<cv::Point2f> &control_points, cv::Mat &window) 
{

    // Each iteration is 0.001. Design steps small enough to make the curve more coherent, otherwise there may be breakpoints
    for (double i = 0.0; i < 1.0; i+=0.001)
    {
        // Each iteration of the for loop computes a locus point on the curve
        auto point = recursive_bezier(control_points, i);
        // The color of the dot is green. Note that the channel is BGR
        window.at<cv::Vec3b>(point.y, point.x)[1] = 255; }}Copy the code

Implementation effect

Complete code and engineering

Complete Project:

Github.com/summer-go/g…

Main.cpp complete code:

#include <chrono>
#include <iostream>
#include <opencv2/opencv.hpp>

std::vector<cv::Point2f> control_points;

int pointsize = 4;

void mouse_handler(int event, int x, int y, int flags, void *userdata) 
{
    if (event == cv::EVENT_LBUTTONDOWN && control_points.size() < pointsize) 
    {
        std::cout << "Left button of the mouse is clicked - position (" << x << ","
        << y << ")" << '\n';
        control_points.emplace_back(x, y); }}void naive_bezier(const std::vector<cv::Point2f> &points, cv::Mat &window) 
{
    auto &p_0 = points[0];
    auto &p_1 = points[1];
    auto &p_2 = points[2];
    auto &p_3 = points[3];

    for (double t = 0.0; t <= 1.0; t += 0.001) 
    {
        auto point = std::pow(1 - t, 3) * p_0 + 3 * t * std::pow(1 - t, 2) * p_1 +
                 3 * std::pow(t, 2) * (1 - t) * p_2 + std::pow(t, 3) * p_3;

        window.at<cv::Vec3b>(point.y, point.x)[2] = 255; }}cv::Point2f lerp_v2f(const cv::Point2f& a, const cv::Point2f& b, float t)
{
    return a + (b - a) * t;
}


/** * Bessel curve recursive algorithm, calculate each T on a curve locus points ** control_points: control Bessel curve points * T: interpolation ratio/weight */
cv::Point2f recursive_bezier(const std::vector<cv::Point2f> &control_points, float t) 
{

    if (control_points.size() = =1) {
        return control_points[0];
    }

    std::vector<cv::Point2f> lerp_points;
    for (size_t i = 1; i < control_points.size(a); i++) { lerp_points.push_back(lerp_v2f(control_points[i - 1], control_points[i], t));
    }
    
    return recursive_bezier(lerp_points, t);

}

/** * trigger Bezier curve interpolation algorithm, get all points ** control_points: control bezier curve points ** window: draw a curve/point window */
void bezier(const std::vector<cv::Point2f> &control_points, cv::Mat &window) 
{

    // Each iteration is 0.001. Design steps small enough to make the curve more coherent, otherwise there may be breakpoints
    for (double i = 0.0; i < 1.0; i+=0.001)
    {
        // Each iteration of the for loop computes a locus point on the curve
        auto point = recursive_bezier(control_points, i);
        // The color of the dot is green. Note that the channel is BGR
        window.at<cv::Vec3b>(point.y, point.x)[1] = 255; }}int main(a) 
{
    cv::Mat window = cv::Mat(700.700, CV_8UC3, cv::Scalar(0));
    cv::cvtColor(window, window, cv::COLOR_BGR2RGB);
    cv::namedWindow("Bezier Curve", cv::WINDOW_AUTOSIZE);

    cv::setMouseCallback("Bezier Curve", mouse_handler, nullptr);

    int key = - 1;
    while(key ! =27) 
    {
        for (auto &point : control_points) 
        {
            cv::circle(window, point, 3, {255.255.255}, 3);
        }

        if (control_points.size() == pointsize) 
        {
            naive_bezier(control_points, window);
            bezier(control_points, window);

            cv::imshow("Bezier Curve", window);
            cv::imwrite("my_bezier_curve.png", window);
            key = cv::waitKey(0);

            return 0;
        }

        cv::imshow("Bezier Curve", window);
        key = cv::waitKey(20);
    }

return 0;
}

Copy the code

Welcome to follow the public account: Sumsmile/focus on image processing mobile development veteran ~~