zoukankan      html  css  js  c++  java
  • 【OpenCV学习】绘制贝赛尔曲线

    作者:gnuhpc
    出处:http://www.cnblogs.com/gnuhpc/

    // 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+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<mark_count;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<<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 = (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<<"==============   Bezier curve DEMO  =============="<<endl;
        cout<<" "<<endl;
        cout<<"1.use mouse to click control point (red) to select a control point"<<endl;
        cout<<"2.use 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<<"4.use '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;
    }
    
    
    

    作者:gnuhpc
    出处:http://www.cnblogs.com/gnuhpc/


                   作者:gnuhpc
                   出处:http://www.cnblogs.com/gnuhpc/
                   除非另有声明,本网站采用知识共享“署名 2.5 中国大陆”许可协议授权。


    分享到:

  • 相关阅读:
    Tomcat性能调优方案
    内存泄露和内存溢出
    HashMap和Hashtable的区别
    properties类是Hashtable的子类
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/gnuhpc/p/2802117.html
Copyright © 2011-2022 走看看