opencv 绘制坐标曲线_【OpenCV学习】绘制贝赛尔曲线

该博客介绍了一个使用OpenCV实现的C++程序,用于在图像上绘制三维贝塞尔曲线。通过定义控制点并调整其位置,可以动态改变曲线形状。程序包括计算贝塞尔曲线的函数、处理鼠标事件来添加或移动控制点,以及根据用户输入调整曲线的精细度。
摘要由CSDN通过智能技术生成

// TrainingTools.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include

#include

#include

#include

#include

#include

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+q

CvPoint3D32f pointAdd(CvPoint3D32f p, CvPoint3D32f q) {

p.x += q.x; p.y += q.y; p.z += q.z;

return p;

}

// 向量和标量相乘p=c*p

CvPoint3D32f 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的index

int getNearPointIndex(CvPoint mouse_pt)

{

CvPoint pt;

for(int i =0; i

{

pt.x= mouse_pt.x - (int)Control_pts[i].x;

pt.y= mouse_pt.y - (int)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<

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 = (float)pt.x;

Control_pts[mark_count].y = (float)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 = (float)x;

Control_pts[conner_pt_index].y = (float)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<

cout<

cout<

cout<

cout<

cout<

cout<

cout<

//初始化四个控制点

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

{

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

{

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<

}

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值