建设银行网站个人中心,个人如何注册微信公众号怎么创建,可视化网页开发,智慧旅游网站建设方案一、问题总览
实现de Casteljau算法来绘制由4个控制点表示的Bzier曲线。需要修改main.cpp中的如下函数#xff1a;
bezier#xff1a;该函数实现绘制Bzier曲线的功能。它使用一个控制点序列和一个OpenCV::Mat对象作为输入#xff0c;没有返回值。它会使t在0到1的范围内进行…一、问题总览
实现de Casteljau算法来绘制由4个控制点表示的Bézier曲线。需要修改main.cpp中的如下函数
bezier该函数实现绘制Bézier曲线的功能。它使用一个控制点序列和一个OpenCV::Mat对象作为输入没有返回值。它会使t在0到1的范围内进行迭代并在每次迭代中使t增加一个微小值。对于每个需要计算的t将调用另一个函数recursive_bezier然后该函数将返回在Bézier曲线上t处的点。最后将返回的点绘制在OpenCV::Mat 对象上。recursive_bezier该函数使用一个控制点序列和一个浮点数t作为输入实现de Casteljau 算法来返回Bézier曲线上对应点的坐标。
二、参考答案
2.1 算法思想
De Casteljau 算法说明如下
考虑一个p0, p1, … pn 为控制点序列的Bézier曲线。首先将相邻的点连接 起来以形成线段。用t : (1 − t) 的比例细分每个线段并找到该分割点。得到的分割点作为新的控制点序列新序列的长度会减少一。如果序列只包含一个点则返回该点并终止。否则使用新的控制点序列并转到步骤1。
使用[0,1] 中的多个不同的t来执行上述算法 例子如下 b 0 b_0 b0, b 1 b_1 b1, b 2 b_2 b2为三个参考点 在 b 0 b 1 b_0b_1 b0b1 上找一点 b 0 1 b_0^1 b01使得 b 0 b 0 1 b_0b_0^1 b0b01 : b 0 1 b 1 b_0^1b_1 b01b1 t : (1 - t) b 1 1 b_1^1 b11 同理 b 0 1 b_0^1 b01 与 b 1 1 b_1^1 b11 作为新的参考点找点 b 0 2 b_0^2 b02使比例关系满足t : (1 - t) b 0 2 b_0^2 b02 就是贝塞尔曲线上的一点使用[0,1] 中的多个不同的t来执行上述算法
2.2 代码实现
2.2.1 Bezier函数的实现
t0 - t1, 调用de Casteljau算法
//cv::Mat window表示屏幕矩阵;矩阵内元素为CV_8UC3类型(无符号8位整数RGB三通道cv::Vec3b)
void bezier(const std::vectorcv::Point2f control_points, cv::Mat window)
{// TODO: Iterate through all t 0 to t 1 with small steps, and call de Casteljaus // recursive Bezier algorithm.for(double t 0.0; t 1.0; t 0.001){cv::Point2f point recursive_bezier(control_points, t);// 绘制坐标(point.y, point.x)的颜色为绿色[1]表示RGB中的Gwindow.atcv::Vec3b(point.y, point.x)[1] 255;}
}2.2.2 Recursive_bezier函数的实现
实现de Casteljau 算法来返回Bézier曲线上对应点的坐标
//cv::Point2f float类型的二维点坐标
cv::Point2f recursive_bezier(const std::vectorcv::Point2f control_points, float t)
{// TODO: Implement de Casteljaus algorithmif(control_points.size() 1) return control_points[0];std::vectorcv::Point2f next_layer_control_points;for(int i 0; i control_points.size() - 1; i){cv::Point2f p0 control_points[i];cv::Point2f p1 control_points[i1];cv::Point2f p2 p0 t * (p1 - p0);next_layer_control_points.push_back(p2);}return recursive_bezier(next_layer_control_points, t);
}2.2.3 实现对贝塞尔曲线的反走样(奖励分数) 对于一个曲线上的点不只把它对应于一个像 素需要根据到像素中心的距离来考虑与它相邻的像素的颜色 P是贝塞尔曲线上t对应的一点P0是周围四个像素区域的交点像素框的中心点为其余四个黑点像素外框都是处于window矩阵整数部分(默认一个window单元格为一个像素)所以p所在的像素框的较近一竖边为min(floor(p.x), ceil(p.x))横边min(floor(p.y), ceil(p.y)) 计算出p0坐标( min(floor(p.x), ceil(p.x))min(floor(p.y), ceil(p.y)) ) 由于像素框大小为1 * 1所以知道P0之后可以计算出周围四个像素中心点坐标根据像素中心点到P点的距离来分配颜色 比如距离p点距离为dist则该点所在像素的G通道 255 * (3 - dist)/3 使用的是哈夫曼距离p离像素中心点最大哈夫曼距离为3
double get_dist(cv::Point2f point1, cv::Point2f point2){//计算两点的哈夫曼距离return fabs(point1.x - point2.x) fabs(point1.y - point2.y);
}//cv::Mat window表示屏幕矩阵;矩阵内元素为CV_8UC3类型(无符号8位整数RGB三通道cv::Vec3b)
void bezier(const std::vectorcv::Point2f control_points, cv::Mat window)
{// TODO: Iterate through all t 0 to t 1 with small steps, and call de Casteljaus // recursive Bezier algorithm.for(double t 0.0; t 1.0; t 0.001){cv::Point2f point recursive_bezier(control_points, t);cv::Point2f point0( std::min(floor(point.x), ceil(point.x)), std::min(floor(point.y), ceil(point.y)) );double dist;std::vectordouble bias{0.5, -0.5};for(int i 0; i 4; i){cv::Point2f centerPoint(point0.x bias[i % 2], point0.y bias[i % 2]);//计算中心点dist get_dist(point, centerPoint);window.atcv::Vec3b(centerPoint.y, centerPoint.x)[1] 255 * (3 - dist) / 3;} }
}三、编译
如往常一样
$ mkdir build
$ cd build
$ cmake ..
$ make$ ./BezierCurve 通过点击屏幕来设置控制点 附件
作业4连接