• Open Source Computer Vision Library

绘制贝赛尔Bezier曲线

Wikipedia,自由的百科全书

在opencv下实现贝赛尔曲线. 可以修改控制点,连接多条曲线,修改曲线精度等操作。

程序示例如下: Image:O_bezier.jpg


运行程序与代码下载

代码如下:

  1. // TrainingTools.cpp : 定义控制台应用程序的入口点。
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include <iostream>
  6. #include <string.h>
  7. #include <cxcore.h>
  8. #include <cv.h>
  9. #include <highgui.h>
  10. #include <fstream>
  11.  
  12. using namespace std;
  13.  
  14. const int WW_MAX_MARK_COUNT = 40; //最大40个控制点
  15. int mark_count =4;
  16. int conner_pt_index =-1;
  17. CvPoint3D32f Control_pts[WW_MAX_MARK_COUNT];
  18. IplImage *image = 0 ; //原始图像
  19. bool is_showControlLines = true;
  20.  
  21.  
  22. // 两个向量相加,p=p+q
  23. CvPoint3D32f pointAdd(CvPoint3D32f p, CvPoint3D32f q) {
  24. p.x += q.x; p.y += q.y; p.z += q.z;
  25. return p;
  26. }
  27.  
  28. // 向量和标量相乘p=c*p
  29. CvPoint3D32f pointTimes(float c, CvPoint3D32f p) {
  30. p.x *= c; p.y *= c; p.z *= c;
  31. return p;
  32. }
  33.  
  34. // 计算贝塞尔方程的值
  35. // 变量u的范围在0-1之间
  36. //P1*t^3 + P2*3*t^2*(1-t) + P3*3*t*(1-t)^2 + P4*(1-t)^3 = Pnew
  37. CvPoint3D32f Bernstein(float u, CvPoint3D32f *p) {
  38. CvPoint3D32f a, b, c, d, r;
  39.  
  40. a = pointTimes(pow(u,3), p[0]);
  41. b = pointTimes(3*pow(u,2)*(1-u), p[1]);
  42. c = pointTimes(3*u*pow((1-u),2), p[2]);
  43. d = pointTimes(pow((1-u),3), p[3]);
  44.  
  45. r = pointAdd(pointAdd(a, b), pointAdd(c, d));
  46.  
  47. return r;
  48. }
  49.  
  50. //画控制线
  51. void DrawControlLine(CvPoint3D32f *p) {
  52.  
  53. CvPoint pc[4];
  54. for(int i=0;i<4;i++)
  55. {
  56. pc[i].x = (int)p[i].x;
  57. pc[i].y = (int)p[i].y;
  58. }
  59.  
  60. cvLine(image,pc[0],pc[1],CV_RGB(0,0,255),1,CV_AA,0);
  61. cvLine(image,pc[2],pc[3],CV_RGB(0,0,255),1,CV_AA,0);
  62. }
  63.  
  64. //得到最近Control_pts的index
  65. int getNearPointIndex(CvPoint mouse_pt)
  66. {
  67. CvPoint pt;
  68. for(int i =0; i<mark_count;i++)
  69. {
  70. pt.x= mouse_pt.x - (int)Control_pts[i].x;
  71. pt.y= mouse_pt.y - (int)Control_pts[i].y;
  72. float distance = sqrt ((float)( pt.x*pt.x + pt.y*pt.y ));
  73. if(distance<10) return i;
  74.  
  75. }
  76. return -1;
  77. }
  78.  
  79. void on_mouse( int event, int x, int y, int flags, void *param )
  80. {
  81. if( event == CV_EVENT_LBUTTONDOWN )
  82. {
  83. CvPoint pt = cvPoint(x,y);
  84. //cout<<x<<","<<y<<endl;
  85.  
  86. if(conner_pt_index >-1)
  87. conner_pt_index = -1;
  88. else
  89. {
  90. conner_pt_index = getNearPointIndex(pt);
  91. //添加新的控制点
  92. if(conner_pt_index==-1)
  93. {
  94. if(mark_count<=(WW_MAX_MARK_COUNT-1))
  95. {
  96. Control_pts[mark_count].x = (float)pt.x;
  97. Control_pts[mark_count].y = (float)pt.y;
  98. Control_pts[mark_count].z = 0;
  99. mark_count++;
  100. }
  101. }
  102. }
  103. }
  104. else if ( event == CV_EVENT_MOUSEMOVE ) //修改控制点坐标
  105. {
  106. if(conner_pt_index >-1)
  107. {
  108. Control_pts[conner_pt_index].x = (float)x;
  109. Control_pts[conner_pt_index].y = (float)y;
  110. }
  111. }
  112.  
  113. };
  114.  
  115.  
  116. int main(int argc, char* argv[])
  117. {
  118.  
  119. CvSize image_sz = cvSize( 1000,1000);
  120. image = cvCreateImage(image_sz , 8, 3 );
  121. cvNamedWindow("Win",0);
  122. cvSetMouseCallback( "Win", on_mouse, 0 );
  123. cvResizeWindow("Win",500,500);
  124.  
  125. cout<<"============== Bezier curve DEMO =============="<<endl;
  126. cout<<" "<<endl;
  127. cout<<"1.use mouse to click control point (red) to select a control point"<<endl;
  128. cout<<"2.use mouse to modify control point"<<endl;
  129. cout<<"3.click mouse on somewhere to add a control point,add three points for add a new curve"<<endl;
  130. cout<<"4.use 'W','S' to add precision or reduce precision."<<endl;
  131. cout<<"5.press 'Z' to show control points."<<endl;
  132. cout<<"===press ESC to exit==="<<endl;
  133.  
  134. //初始化四个控制点
  135. Control_pts[0].x = 200;
  136. Control_pts[0].y = 200;
  137. Control_pts[0].z = 0;
  138.  
  139. Control_pts[1].x = 300;
  140. Control_pts[1].y = 500;
  141. Control_pts[1].z = 0;
  142.  
  143. Control_pts[2].x = 400;
  144. Control_pts[2].y = 560;
  145. Control_pts[2].z = 0;
  146.  
  147. Control_pts[3].x = 500;
  148. Control_pts[3].y = 100;
  149. Control_pts[3].z = 0;
  150.  
  151. int divs = 50; //控制精细度
  152.  
  153. for(;;)
  154. {
  155.  
  156. CvPoint pt_now,pt_pre;
  157. cvZero(image);
  158.  
  159.  
  160. //绘制控制点
  161. if(is_showControlLines)
  162. {
  163. for(int i =0;i<mark_count;i++)
  164. {
  165. CvPoint ptc;
  166. ptc.x = (int) Control_pts[i].x;
  167. ptc.y = (int) Control_pts[i].y;
  168. cvCircle( image, ptc, 4, CV_RGB(255,0,0), 1,CV_AA, 0);
  169. }
  170. }
  171.  
  172. //绘制Bezier曲线
  173. CvPoint3D32f *pControls = Control_pts;
  174. for(int j=0;j<mark_count-3;j+=3)
  175. {
  176. for (int i=0;i<=divs;i++)
  177. {
  178. float u = (float)i/divs;
  179. CvPoint3D32f newPt = Bernstein(u,pControls);
  180.  
  181. pt_now.x = (int)newPt.x;
  182. pt_now.y = (int)newPt.y;
  183.  
  184. if(i>0) cvLine(image,pt_now,pt_pre,CV_RGB(230,255,0),2,CV_AA, 0 );
  185. pt_pre = pt_now;
  186. }
  187.  
  188. //画控制线
  189. if(is_showControlLines)DrawControlLine(pControls);
  190. pControls+=3;
  191. }
  192.  
  193. cvShowImage("Win",image);
  194. int keyCode = cvWaitKey(20);
  195. if (keyCode==27) break;
  196. if(keyCode=='w'||keyCode=='W') divs+=2;
  197. if(keyCode=='s'||keyCode=='S') divs-=2;
  198. if(keyCode=='z'||keyCode=='Z') is_showControlLines = is_showControlLines^1;
  199.  
  200. //cout<<"precision : "<<divs<<endl;
  201.  
  202. }
  203. return 0;
  204. }
  205.  
Views
Personal tools