在opencv下绘制Bezier 贝赛尔 曲线
- 格式:doc
- 大小:38.00 KB
- 文档页数:5
OpenCV三阶贝塞尔曲线1. 简介贝塞尔曲线是计算机图形学中常用的一种曲线表示方法,可以通过一系列控制点来描述曲线的形状。
OpenCV是一个功能强大的开源计算机视觉库,提供了丰富的图像处理和计算机视觉算法。
本文将介绍如何使用OpenCV实现三阶贝塞尔曲线。
2. 贝塞尔曲线概述贝塞尔曲线由一系列控制点和插值点构成。
控制点用于定义曲线的形状,而插值点则用于描述曲线的平滑程度。
贝塞尔曲线可以是一阶、二阶、三阶或更高阶的,本文将重点介绍三阶贝塞尔曲线。
三阶贝塞尔曲线由四个控制点P0、P1、P2和P3定义,其中P0和P3是曲线的起点和终点,P1和P2则用于控制曲线的形状。
曲线上的点可以通过参数t在[0, 1]范围内进行插值计算,公式如下:B(t) = (1-t)^3 * P0 + 3 * (1-t)^2 * t * P1 + 3 * (1-t) * t^2 * P2 + t^3 * P33. OpenCV实现使用OpenCV实现三阶贝塞尔曲线的步骤如下:3.1 导入库首先,需要导入OpenCV库。
import cv2import numpy as np3.2 创建画布创建一个空白画布,并设置画布的大小和背景色。
width, height = 800, 600canvas = np.zeros((height, width, 3), dtype=np.uint8)canvas.fill(255) # 设置背景色为白色3.3 定义控制点定义四个控制点的坐标,分别为P0、P1、P2和P3。
P0 = (100, 300)P1 = (200, 100)P2 = (600, 500)P3 = (700, 300)3.4 绘制控制点在画布上绘制四个控制点,可以使用OpenCV的cv2.circle()函数实现。
radius = 5color = (0, 0, 255) # 红色thickness = -1 # 填充cv2.circle(canvas, P0, radius, color, thickness)cv2.circle(canvas, P1, radius, color, thickness)cv2.circle(canvas, P2, radius, color, thickness)cv2.circle(canvas, P3, radius, color, thickness)3.5 计算并绘制曲线使用参数t在[0, 1]范围内进行插值计算,并在画布上绘制曲线。
C语言实现生成贝塞尔曲线(代码)贝塞尔曲线是一种数学曲线,经常用于计算机图形学中。
他们有许多应用,从简单2D 图形到高级3D建模,甚至包括游戏引擎和动画。
在这篇文章中,我们将介绍如何用C语言实现贝塞尔曲线的生成算法。
贝塞尔曲线是通过将一系列点连接起来形成的曲线。
在这些点之间,我们添加了一些称为控制点的点。
这些控制点决定了曲线的形状和弯曲程度。
在绘制贝塞尔曲线之前,我们需要先实现一个计算两个点之间距离的函数。
这个函数非常简单,可以使用勾股定理计算两个点之间的距离。
double distance(int x1, int y1, int x2, int y2) {return sqrt(pow((x2 - x1), 2) + pow((y2 - y1), 2));}接下来,我们需要实现一个贝塞尔曲线点的函数。
给出起点、终点和控制点,则该函数返回根据这些点计算的贝塞尔曲线上的点。
为了简单起见,我们将实现三次贝塞尔曲线。
需要注意的是,我们需要将弧上的点插入到数组中以便最终绘制曲线。
void bezier(int x1, int y1, int x2, int y2, int cx1, int cy1, int cx2, int cy2, Point* points, int& n) {for (double t = 0; t <= 1; t += 0.01) {double xt = pow(1 - t, 3) * x1 + 3 * t * pow(1 - t, 2) * cx1 + 3 * pow(t, 2) * (1 - t) * cx2 + pow(t, 3) * x2;double yt = pow(1 - t, 3) * y1 + 3 * t * pow(1 - t, 2) * cy1 + 3 * pow(t, 2) * (1 - t) * cy2 + pow(t, 3) * y2;points[n].x = round(xt);points[n].y = round(yt);n++;}points[n].x = x2;points[n].y = y2;n++;}在上面的代码中,我们使用了一个for循环来遍历弧上的点。
绘制Bezier曲线编程及说明整体方案:(1)单击鼠标左键绘制控制点(不超过10个顶点),并自动连接为控制多边形。
(2)单击鼠标右键确定绘制Bezier曲线完毕。
(3)绘制时鼠标显示坐标。
(4)点击控制点可以改变Bezier曲线形状。
(5)可以使用鼠标或者键盘输入坐标绘制Bezier曲线。
关键技术:最小二乘法,曲线拟合,MFC框架编程Bezier曲线编程算法:// JjbView.cpp : implementation of the CJjbView class//#include "stdafx.h"#include "Jjb.h"#include "JjbDoc.h"#include "JjbView.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CJjbViewIMPLEMENT_DYNCREATE(CJjbView, CView)BEGIN_MESSAGE_MAP(CJjbView, CView)//{{AFX_MSG_MAP(CJjbView)ON_COMMAND(ID_BEZIER, OnBezier)ON_WM_LBUTTONDOWN()ON_WM_LBUTTONUP()ON_WM_MOUSEMOVE()ON_WM_RBUTTONDOWN()//}}AFX_MSG_MAP// Standard printing commandsON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CJjbView construction/destructiondouble J(int n,int i);double C(int n,int i);double N(double u,int n);int JieCheng(int n);//构造函数CJjbView::CJjbView(){// TODO: add construction code herem_bIsChoosed=false;m_bStopDraw=false;m_bMakeSure=false;m_eChooseType=Bezier;while (m_vInputPoint.size()!=0){m_vInputPoint.pop_back();}while (m_vControlPoint.size()!=0){m_vControlPoint.pop_back();}while (m_vXiShu.size()!=0){m_vXiShu.pop_back();}}//析构函数CJjbView::~CJjbView(){while (m_vInputPoint.size()!=0){m_vInputPoint.pop_back();}while (m_vControlPoint.size()!=0){m_vControlPoint.pop_back();}while (m_vXiShu.size()!=0){m_vXiShu.pop_back();}}BOOL CJjbView::PreCreateWindow(CREATESTRUCT& cs) //定义窗口{// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT csreturn CView::PreCreateWindow(cs);}/////////////////////////////////////////////////////////////////////////////// CJjbView drawing// 刷新时绘图void CJjbView::OnDraw(CDC* pDC){CJjbDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// TODO: add draw code for native data hereGetClientRect(&rect);if (m_eMouseStatus==MouseMove&&m_bStopDraw==false){m_vInputPoint.push_back(m_cMovePoint);}CString str;CClientDC d(this);int i;if(m_bIsChoosed==true){if (m_bStopDraw==false){str.Format(" X=%d,y=%d ]",m_cMovePoint.x,m_cMovePoint.y);d.TextOut(m_cMovePoint.x+10,m_cMovePoint.y+10,str);}switch(m_eChooseType)//菜单选择{case Bezier: //选择后的窗口状态str.Format("Bezier曲线,点击右键表示确定,移动节点改变形状。
计算机图形学作业3姓名学号班级作业内容绘制一个“Bezier”曲线效果截图关键程序(<40行) #include<gl/glut.h>void Initial(void){glClearColor(0,0,0,0);glLineWidth(1);GLfloat ControlP[4][3]={{-66,-88,0},{-44,55,0},{22,-33,0},{77,66,0}};glMap1f(GL_MAP1_VERTEX_3,0,1,3,4,*ControlP);glEnable(GL_MAP1_VERTEX_3);}void Display(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1,0,0);glMapGrid1f(100,0,1);glEvalMesh1(GL_LINE,0,100);glFlush();}void Reshape(GLint newWidth,GLint newHeight){glViewport(0,0,newWidth,newHeight);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(-100,100,-100,100);}void main(){glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); //使用双缓存及RGB模型glutInitWindowSize(666, 488); //指定窗口的尺寸glutInitWindowPosition(288, 155); //指定窗口在屏幕上的位置glutCreateWindow("朱");Initial();glutDisplayFunc(Display);glutReshapeFunc(Reshape);glutMainLoop();}小结这一次的用OpenGL绘制贝塞尔曲线实验比上一次花了更长的时间,原来以为对OpenGL应该算是有了一些了解,这次实验过后发现,没搞明白的尚且有许多,更不用提还有许多根本不知道的应用方法。
Bezier 曲线绘制实验文档
2005.10
一、实验目的
编程实现中点分割法绘制Bezier曲线。
二、实现功能
实验程序通过OpenGL实现,可以通过鼠标单击左键绘制Bezier控制点,单击右键结束控制点绘制并显示Bezier曲线。
单击控制点可以选择控制点,这个时候可以通过拖拽移动控制点,同时Bezier曲线的变化也将反应;按键盘上的d可以删除控制点,i可以在这个控制点和下一个控制点的中点位置增加一个新的控制点。
按c可以清除所有内容以重新绘制。
通过上下键可以增加或者缩小阈值。
三、程序实现
1、Bezier曲线绘制算法
函数calBezier通过中点分割法绘制Bezier曲线。
利用递归的方法实现,calPiece是递归子函数。
算法伪码描述如下:
考虑到最后需要求出2n-1个控制点,因此预先将n个控制点间隔排列放到大小为2n-1的数组中。
之后对于每一层次的求解,将两个控制点的中点求出来的结果放到这两个控制点所在数组序号中间的位置即可。
如下表所示(4个控制点)。
表中红色的内容为每一个循环中需要计算的内容,使用其上一行中序号在前一位和后一位的控制点的中点。
最后结果前4项就是第一段Bezier曲线的控制点,后4项就是第二段Bezier曲线的控制点。
3、OpenGL函数
四、实验结果
在VS2003+WinXP平台下实现了程序。
opencv 贝塞尔曲线贝塞尔曲线简介贝塞尔曲线是一种数学曲线,由法国工程师Pierre Bézier在20世纪50年代提出,用于计算机图形学和计算机辅助设计中的曲线插值。
它通过在给定的控制点上进行插值来生成曲线,具有平滑、连续和可调控的特点。
贝塞尔曲线广泛应用于计算机图形学、计算机辅助设计、动画与游戏开发等领域。
贝塞尔曲线的控制点贝塞尔曲线的生成是基于一组控制点的插值计算。
通常情况下,贝塞尔曲线的控制点包括起始点、终止点和若干个中间点。
起始点和终止点为曲线的起点和终点,而中间点则决定了曲线的形状。
通过控制点的位置和数量的调整,可以获得不同形状的贝塞尔曲线。
贝塞尔曲线的计算方法贝塞尔曲线的计算方法主要有两种:de Casteljau算法和求解贝塞尔曲线参数值的方程求解法。
de Casteljau算法de Casteljau算法是一种递归的计算方法,通过不断地对控制点进行插值,最终得到贝塞尔曲线的坐标。
其具体步骤如下:1.将控制点按照递增的参数值t进行排序;2.初始化插值的控制点集合为原始控制点集合;3.对插值的控制点集合中的每个点,根据参数值t进行插值计算,得到插值后的新点,并将新点加入到插值的控制点集合中;4.重复步骤3,直到插值的控制点集合中只剩下一个点,该点即为贝塞尔曲线上的一个坐标。
方程求解法求解贝塞尔曲线参数值的方程求解法通过求解多项式方程组来计算贝塞尔曲线的坐标。
设贝塞尔曲线的控制点为P0,P1,...,P n,贝塞尔曲线的参数值为t,则贝塞尔曲线的坐标可以表示为:n⋅B i n(t)B(t)=∑P ii=0其中,B i n(t)是n次贝塞尔基函数,可以表示为:B i n(t)=C n i⋅(1−t)n−i⋅t i求解方程组的方法有多种,可以使用牛顿法、二分法等。
opencv中的贝塞尔曲线绘制opencv是一个开源的计算机视觉库,提供了丰富的图像处理和计算机视觉算法。
opencv中可以通过函数cv::bezierCurveTo来绘制贝塞尔曲线。
实验七 3D编程及Bezier曲线曲面绘制一、实验目的1.3D编程:熟悉视点观察函数的设置和使用;熟悉投影变换函数的设置和使用;熟悉基本3D 图元的绘制2.了解OpenGL绘制Bezier曲线的方法二、实验环境硬件要求:PC机,主流配置,最好为独立显卡,显存512M以上。
软件环境:操作系统:Windows XP。
语言开发工具:VC6.0。
三、实验要求:按照实验内容做实验,保留所作步骤效果截图或演示程序,当场检查,现场计分四、实验内容1.3D编程3D Cube.cpp 为一静止3D立方体,3D Cube2.cpp 为正交投影下的旋转3D立方体,按下鼠标可实现不同方向的旋转。
分析3D编程代码与程序结构。
图7-1 静止立方体效果图图7-2 旋转立方体效果图图7-3 旋转茶壶和圆环效果图1.让静止的立方体绕Z轴不停旋转2.修改视点,目标点不变,观看显示效果3. 修改目标点,视点不动,观看显示效果4. 视点与目标点同时修改,观看显示效果5. 视点与目标点不变,修改观察体大小,观看显示效果6. 将正交投影观察体改为透视投影观察体,并设置其大小,观察显示效果7. 将立方体替换为茶壶,观看显示效果.选做2.Bezier曲线绘制BezierCurve.cpp为绘制bezier曲线的源程序,仔细研读源程序,并作如下修改1).改变控制点,观察曲线和曲面形状的变化,控制点起什么作用?2).改写bezier.cpp,增加控制点数目,修改控制点位置,使之成为空间封闭曲线,写出修改的关键代码及注释(TIPS:OpenGLBezier曲线绘制方法最多只能有8个控制点)3).根据bezier曲线的性质,改写程序,使之成为两段曲线光滑连接。
每段曲线用不同颜色表示,并画出控制点。
图7-2·Bezier曲线绘制效果五、函数参考(一)3D编程1.视点设置函数void gluLookAt(GLdouble eyex, GLdouble eyey,GLdouble eyez,GLdouble atx,GLdouble aty,GLdouble atz,GLdouble upx,GLdouble upy,GLdouble upz)给出矩阵作用于当前矩阵,定义相机位置和方向视点:eyex, eyey, eyez目标点:atx,aty,atz相机向上方向:upx,upy,upz如果不引用该函数,则eyex=0,eyey=0,eyez=0,atx=0,aty=0,atz=-1,Upx=0,upy=1,upz=0此函数放在display函数中调用参考坐标系:世界坐标系2.正交投影变换设置函数. void glOrtho(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far),建立正交投影矩阵,定义一个正平行观察体。
在opencv下绘制Bezier 贝赛尔曲线2008-11-01 01:31因需要研究了一下贝赛尔曲线,并在opencv下实现. 可以修改控制点,连接多条曲线,修改曲线精度。
// TrainingTools.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"#include <iostream>#include <string.h>#include <cxcore.h>#include <cv.h>#include <highgui.h>#include <fstream>using namespace std;const int WW_MAX_MARK_COUNT = 40; //最大40个控制点int mark_count =4;int conner_pt_index =-1;CvPoint3D32f Control_pts[WW_MAX_MARK_COUNT];IplImage *image = 0 ; //原始图像bool is_showControlLines = true;// 两个向量相加,p=p+qCvPoint3D32f pointAdd(CvPoint3D32f p, CvPoint3D32f q) ...{p.x += q.x; p.y += q.y; p.z += q.z;return p;}// 向量和标量相乘p=c*pCvPoint3D32f pointTimes(float c, CvPoint3D32f p) ...{p.x *= c; p.y *= c; p.z *= c;return p;}// 计算贝塞尔方程的值// 变量u的范围在0-1之间//P1*t^3 + P2*3*t^2*(1-t) + P3*3*t*(1-t)^2 + P4*(1-t)^3 = Pnew CvPoint3D32f Bernstein(float u, CvPoint3D32f *p) ...{CvPoint3D32f a, b, c, d, r;a = pointTimes(pow(u,3), p[0]);b = pointTimes(3*pow(u,2)*(1-u), p[1]);c = pointTimes(3*u*pow((1-u),2), p[2]);d = pointTimes(pow((1-u),3), p[3]);r = pointAdd(pointAdd(a, b), pointAdd(c, d));return r;}//画控制线void DrawControlLine(CvPoint3D32f *p) ...{CvPoint pc[4];for(int i=0;i<4;i++)...{pc[i].x = (int)p[i].x;pc[i].y = (int)p[i].y;}cvLine(image,pc[0],pc[1],CV_RGB(0,0,255),1,CV_AA,0);cvLine(image,pc[2],pc[3],CV_RGB(0,0,255),1,CV_AA,0);}//得到最近Control_pts的indexint getNearPointIndex(CvPoint mouse_pt)...{CvPoint pt;for(int i =0; i<mark_count;i++)...{pt.x= mouse_pt.x - Control_pts[i].x;pt.y= mouse_pt.y - Control_pts[i].y;float distance = sqrt ((float)( pt.x*pt.x + pt.y*pt.y )); if(distance<10) return i;}return -1;}void on_mouse( int event, int x, int y, int flags, void *param ) ...{if( event == CV_EVENT_LBUTTONDOWN )...{CvPoint pt = cvPoint(x,y);//cout<<x<<","<<y<<endl;if(conner_pt_index >-1)conner_pt_index = -1;else...{conner_pt_index = getNearPointIndex(pt);//添加新的控制点if(conner_pt_index==-1)...{if(mark_count<=(WW_MAX_MARK_COUNT-1))...{Control_pts[mark_count].x = pt.x;Control_pts[mark_count].y = pt.y;Control_pts[mark_count].z = 0;mark_count++;}}}}else if ( event == CV_EVENT_MOUSEMOVE ) //修改控制点坐标...{if(conner_pt_index >-1)...{Control_pts[conner_pt_index].x = x;Control_pts[conner_pt_index].y = y;}}};int main(int argc, char* argv[])...{CvSize image_sz = cvSize( 1000,1000);image = cvCreateImage(image_sz , 8, 3 );cvNamedWindow("Win",0);cvSetMouseCallback( "Win", on_mouse, 0 );cvResizeWindow("Win",500,500);cout<<"============== Bezier curve DEMO =============="<<endl; cout<<" "<<endl;cout<<"e mouse to click control point (red) to select a control point"<<endl;cout<<"e mouse to modify control point"<<endl;cout<<"3.click mouse on somewhere to add a control point,add three points for add a new curve"<<endl;cout<<"e 'W','S' to add precision or reduce precision."<<endl; cout<<"5.press 'Z' to show control points."<<endl;cout<<"===press ESC to exit==="<<endl;//初始化四个控制点Control_pts[0].x = 200;Control_pts[0].y = 200;Control_pts[0].z = 0;Control_pts[1].x = 300;Control_pts[1].y = 500;Control_pts[1].z = 0;Control_pts[2].x = 400;Control_pts[2].y = 560;Control_pts[2].z = 0;Control_pts[3].x = 500;Control_pts[3].y = 100;Control_pts[3].z = 0;int divs = 50; //控制精细度for(;;)...{CvPoint pt_now,pt_pre;cvZero(image);//绘制控制点if(is_showControlLines)...{for(int i =0;i<mark_count;i++)...{CvPoint ptc;ptc.x = (int) Control_pts[i].x;ptc.y = (int) Control_pts[i].y;cvCircle( image, ptc, 4, CV_RGB(255,0,0), 1,CV_AA, 0);}}//绘制Bezier曲线CvPoint3D32f *pControls = Control_pts;for(int j=0;j<mark_count-3;j+=3)...{for (int i=0;i<=divs;i++)...{float u = (float)i/divs;CvPoint3D32f newPt =Bernstein(u,pControls);pt_now.x = (int)newPt.x;pt_now.y = (int)newPt.y;if(i>0) cvLine(image,pt_now,pt_pre,CV_RGB(230,255, 0),2,CV_AA, 0 );pt_pre = pt_now;}//画控制线if(is_showControlLines)DrawControlLine(pControls);pControls+=3;}cvShowImage("Win",image);int keyCode = cvWaitKey(20);if (keyCode==27) break;if(keyCode=='w'||keyCode=='W') divs+=2;if(keyCode=='s'||keyCode=='S') divs-=2;if(keyCode=='z'||keyCode=='Z') is_showControlLines =is_showControlLines^1;//cout<<"precision : "<<divs<<endl;}return 0;}。
bezier曲线代码实现一、什么是贝塞尔曲线?贝塞尔曲线是一种数学曲线,它使用一组控制点来定义一条曲线。
它在计算机图形学、汽车设计和电子游戏等领域得到了广泛的应用。
二、贝塞尔曲线的类型1. 二次贝塞尔曲线:由三个点定义,包括起始点、控制点和结束点。
2. 三次贝塞尔曲线:由四个点定义,包括起始点、两个控制点和结束点。
三、贝塞尔曲线的实现1. 二次贝塞尔曲线的实现:```pythonimport pygamedef quadratic_bezier(points, num_divisions):x0, y0 = points[0]x1, y1 = points[1]x2, y2 = points[2]for i in range(num_divisions):t = i / num_divisionsx = (1 - t)**2 * x0 + 2 * (1 - t) * t * x1 + t**2 * x2y = (1 - t)**2 * y0 + 2 * (1 - t) * t * y1 + t**2 * y2pygame.draw.line(screen, (255, 255, 255), (x, y), (x, y))```2. 三次贝塞尔曲线的实现:```pythonimport pygamedef cubic_bezier(points, num_divisions):x0, y0 = points[0]x1, y1 = points[1]x2, y2 = points[2]x3, y3 = points[3]for i in range(num_divisions):t = i / num_divisionsx = (1 - t)**3 * x0 + 3 * (1 - t)**2 * t * x1 + 3 * (1 - t) * t**2 * x2 + t**3 * x3y = (1 - t)**3 * y0 + 3 * (1 - t)**2 * t * y1 + 3 * (1 - t) * t**2 * y2 + t**3 * y3pygame.draw.line(screen, (255, 255, 255), (x, y), (x, y))```四、总结贝塞尔曲线是一种非常有用的数学工具,它可以被用于多种领域。
bezier曲线绘制算法贝塞尔曲线绘制算法贝塞尔曲线是一种常用于计算机图形学中的数学曲线,具有平滑弯曲的特性。
通过控制点的位置和数量,可以绘制出各种形状的曲线,如圆弧、曲线等。
本文将介绍贝塞尔曲线绘制算法的基本原理和实现方法。
1. 贝塞尔曲线的基本概念贝塞尔曲线由两个或多个控制点决定,通过这些控制点的位置,可以确定曲线的形状和轨迹。
其中,起始点和结束点称为锚点,而其他点称为控制点。
贝塞尔曲线的形状由控制点之间的插值和权重决定,权重决定了每个控制点对曲线形状的影响程度。
2. 二次贝塞尔曲线绘制算法二次贝塞尔曲线由三个点决定,分别是起始点P0、控制点P1和结束点P2。
绘制二次贝塞尔曲线的算法如下:(1) 将曲线分为若干个线段,每段用t从0到1进行插值。
(2) 根据插值参数t,计算控制点P0、P1和P2在x和y轴上的值。
(3) 绘制连接P0和P1的线段,连接P1和P2的线段。
3. 三次贝塞尔曲线绘制算法三次贝塞尔曲线由四个点决定,分别是起始点P0、控制点P1、P2和结束点P3。
绘制三次贝塞尔曲线的算法如下:(1) 将曲线分为若干个线段,每段用t从0到1进行插值。
(2) 根据插值参数t,计算控制点P0、P1、P2和P3在x和y轴上的值。
(3) 绘制连接P0和P1的线段,连接P1和P2的线段,以及连接P2和P3的线段。
4. 高阶贝塞尔曲线的绘制算法除了二次和三次贝塞尔曲线,还存在更高阶的贝塞尔曲线。
对于n 阶贝塞尔曲线,需要n+1个点来确定。
其绘制算法与二次和三次贝塞尔曲线类似,通过插值参数t来计算各个控制点的值,并连接相邻控制点。
5. 贝塞尔曲线的应用贝塞尔曲线在计算机图形学中有广泛的应用,常用于绘制平滑曲线、图形变形、字体设计等方面。
在计算机动画、游戏开发等领域,贝塞尔曲线的应用也非常广泛。
贝塞尔曲线是一种常用于计算机图形学中的数学曲线,通过控制点的位置和数量,可以绘制出各种形状的曲线。
本文介绍了贝塞尔曲线的基本概念,以及二次、三次和高阶贝塞尔曲线的绘制算法。
在opencv下绘制Bezier 贝赛尔曲线2008-11-01 01:31因需要研究了一下贝赛尔曲线,并在opencv下实现. 可以修改控制点,连接多条曲线,修改曲线精度。
// TrainingTools.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"#include <iostream>#include <string.h>#include <cxcore.h>#include <cv.h>#include <highgui.h>#include <fstream>using namespace std;const int WW_MAX_MARK_COUNT = 40; //最大40个控制点int mark_count =4;int conner_pt_index =-1;CvPoint3D32f Control_pts[WW_MAX_MARK_COUNT];IplImage *image = 0 ; //原始图像bool is_showControlLines = true;// 两个向量相加,p=p+qCvPoint3D32f pointAdd(CvPoint3D32f p, CvPoint3D32f q) ...{p.x += q.x; p.y += q.y; p.z += q.z;return p;}// 向量和标量相乘p=c*pCvPoint3D32f pointTimes(float c, CvPoint3D32f p) ...{p.x *= c; p.y *= c; p.z *= c;return p;}// 计算贝塞尔方程的值// 变量u的范围在0-1之间//P1*t^3 + P2*3*t^2*(1-t) + P3*3*t*(1-t)^2 + P4*(1-t)^3 = Pnew CvPoint3D32f Bernstein(float u, CvPoint3D32f *p) ...{CvPoint3D32f a, b, c, d, r;a = pointTimes(pow(u,3), p[0]);b = pointTimes(3*pow(u,2)*(1-u), p[1]);c = pointTimes(3*u*pow((1-u),2), p[2]);d = pointTimes(pow((1-u),3), p[3]);r = pointAdd(pointAdd(a, b), pointAdd(c, d));return r;}//画控制线void DrawControlLine(CvPoint3D32f *p) ...{CvPoint pc[4];for(int i=0;i<4;i++)...{pc[i].x = (int)p[i].x;pc[i].y = (int)p[i].y;}cvLine(image,pc[0],pc[1],CV_RGB(0,0,255),1,CV_AA,0);cvLine(image,pc[2],pc[3],CV_RGB(0,0,255),1,CV_AA,0);}//得到最近Control_pts的indexint getNearPointIndex(CvPoint mouse_pt)...{CvPoint pt;for(int i =0; i<mark_count;i++)...{pt.x= mouse_pt.x - Control_pts[i].x;pt.y= mouse_pt.y - Control_pts[i].y;float distance = sqrt ((float)( pt.x*pt.x + pt.y*pt.y )); if(distance<10) return i;}return -1;}void on_mouse( int event, int x, int y, int flags, void *param ) ...{if( event == CV_EVENT_LBUTTONDOWN )...{CvPoint pt = cvPoint(x,y);//cout<<x<<","<<y<<endl;if(conner_pt_index >-1)conner_pt_index = -1;else...{conner_pt_index = getNearPointIndex(pt);//添加新的控制点if(conner_pt_index==-1)...{if(mark_count<=(WW_MAX_MARK_COUNT-1))...{Control_pts[mark_count].x = pt.x;Control_pts[mark_count].y = pt.y;Control_pts[mark_count].z = 0;mark_count++;}}}}else if ( event == CV_EVENT_MOUSEMOVE ) //修改控制点坐标...{if(conner_pt_index >-1)...{Control_pts[conner_pt_index].x = x;Control_pts[conner_pt_index].y = y;}}};int main(int argc, char* argv[])...{CvSize image_sz = cvSize( 1000,1000);image = cvCreateImage(image_sz , 8, 3 );cvNamedWindow("Win",0);cvSetMouseCallback( "Win", on_mouse, 0 );cvResizeWindow("Win",500,500);cout<<"============== Bezier curve DEMO =============="<<endl; cout<<" "<<endl;cout<<"e mouse to click control point (red) to select a control point"<<endl;cout<<"e mouse to modify control point"<<endl;cout<<"3.click mouse on somewhere to add a control point,add three points for add a new curve"<<endl;cout<<"e 'W','S' to add precision or reduce precision."<<endl; cout<<"5.press 'Z' to show control points."<<endl;cout<<"===press ESC to exit==="<<endl;//初始化四个控制点Control_pts[0].x = 200;Control_pts[0].y = 200;Control_pts[0].z = 0;Control_pts[1].x = 300;Control_pts[1].y = 500;Control_pts[1].z = 0;Control_pts[2].x = 400;Control_pts[2].y = 560;Control_pts[2].z = 0;Control_pts[3].x = 500;Control_pts[3].y = 100;Control_pts[3].z = 0;int divs = 50; //控制精细度for(;;)...{CvPoint pt_now,pt_pre;cvZero(image);//绘制控制点if(is_showControlLines)...{for(int i =0;i<mark_count;i++)...{CvPoint ptc;ptc.x = (int) Control_pts[i].x;ptc.y = (int) Control_pts[i].y;cvCircle( image, ptc, 4, CV_RGB(255,0,0), 1,CV_AA, 0);}}//绘制Bezier曲线CvPoint3D32f *pControls = Control_pts;for(int j=0;j<mark_count-3;j+=3)...{for (int i=0;i<=divs;i++)...{float u = (float)i/divs;CvPoint3D32f newPt =Bernstein(u,pControls);pt_now.x = (int)newPt.x;pt_now.y = (int)newPt.y;if(i>0) cvLine(image,pt_now,pt_pre,CV_RGB(230,255, 0),2,CV_AA, 0 );pt_pre = pt_now;}//画控制线if(is_showControlLines)DrawControlLine(pControls);pControls+=3;}cvShowImage("Win",image);int keyCode = cvWaitKey(20);if (keyCode==27) break;if(keyCode=='w'||keyCode=='W') divs+=2;if(keyCode=='s'||keyCode=='S') divs-=2;if(keyCode=='z'||keyCode=='Z') is_showControlLines =is_showControlLines^1;//cout<<"precision : "<<divs<<endl;}return 0;}。