HomeWork 4:Bézier 曲线
这个挺简单的,挺有意思的:
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| 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 recursive_bezier(const std::vector<cv::Point2f> &control_points, float t) { if(control_points.size() == 1) return control_points[0];
std::vector<cv::Point2f> temp_control_points; for(int i = 0; i < control_points.size()-1; i ++) { cv::Point2f temp_point = control_points[i] - (control_points[i] - control_points[i+1]) * t; temp_control_points.push_back(temp_point); }
return recursive_bezier(temp_control_points, t); }
void bezier(const std::vector<cv::Point2f> &control_points, cv::Mat &window) { for(float t = 0; t <= 1; t += 0.001f) { cv::Point2f point = recursive_bezier(control_points, t); window.at<cv::Vec3b>(point.y, point.x)[1] = 255; } }
|
下面是贝塞尔曲线:
红色:公式
绿色:递归
黄色:两个同时调用的结果
提高:(反走样)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
void bezier_2(const std::vector<cv::Point2f> &control_points, cv::Mat &window) { for (float t = 0.0; t <= 1.0; t += 0.001) { cv::Point2f point = recursive_bezier(control_points, t);
cv::Point2i p0; p0.x = point.x-std::floor(point.x) < 0.5 ? std::floor(point.x) : std::ceil(point.x); p0.y = point.y-std::floor(point.y) < 0.5 ? std::floor(point.y) : std::ceil(point.y);
std::vector<cv::Point2i> ps; ps.push_back(p0); ps.push_back(cv::Point2i(p0.x-1, p0.y)); ps.push_back(cv::Point2i(p0.x, p0.y-1)); ps.push_back(cv::Point2i(p0.x-1, p0.y-1)); float sum_d = 0.0f; float max_d = sqrt(2); std::vector<float> ds = {}; for (int i = 0; i < 4; i++) { cv::Point2f cp(ps[i].x + 0.5f, ps[i].y + 0.5f); float d = max_d - std::sqrt(std::pow(point.x - cp.x, 2) + std::pow(point.y - cp.y, 2)); ds.push_back(d); sum_d += d; }
for (int i = 0; i < 4; i++) { float k = ds[i] / sum_d; window.at<cv::Vec3b>(ps[i].y, ps[i].x)[1] = std::min(255.f, window.at<cv::Vec3b>(ps[i].y, ps[i].x)[1] + 255.f * k); } } }
|
反走样对比,效果还是挺明显的: