www.pudn.com > B-spline.zip > bspline.cpp, change:2012-03-20,size:4072b


#include<cv.h> 
#include<cxcore.h> 
#include<highgui.h> 
 
#include<math.h> 
#include"bspline.h" 
 
#pragma comment (lib,"cv210.lib") 
#pragma comment (lib,"cxcore210.lib") 
#pragma comment (lib,"highgui210.lib") 
 
void B_SPLine::InitMouseControlPoint(char *windowName,IplImage *img) 
{ 
	cvZero(img); 
	m_MouseParam.img=img; 
	m_MouseParam.pclass=this; 
	cvSetMouseCallback(windowName,MouseCallback,(void *)&m_MouseParam); 
} 
 
void B_SPLine::DrawBSPLine(IplImage *img) 
{ 
	int x,y; 
	unsigned char *p; 
	float u; 
	std::list<ControlPoint>::iterator iter; 
 
	cvZero(img); 
	ControlPoint result; 
	for(iter=m_ControlPoints.begin();iter!=m_ControlPoints.end();++iter) 
	{ 
		p=(unsigned char *)(img->imageData+iter->point.x*img->nChannels+iter->point.y*img->widthStep); 
		*p=255; 
	} 
 
	for(u=0;u<1.0;u+=0.002) 
	{ 
		GetBSPLine(u,&result); 
		p=(unsigned char *)(img->imageData+result.point.x*img->nChannels+result.point.y*img->widthStep); 
		*p=128; 
	} 
} 
 
void B_SPLine::GetURegion(float u) 
{ 
	int i,N; 
	N=m_ControlPoints.size(); 
	m_DeltaU=1.0/N; 
	m_LowerBoundIdx=(int)(u/m_DeltaU); 
	m_LowerBound=m_LowerBoundIdx*m_DeltaU; 
	m_UpperBound=m_DeltaU+m_LowerBound; 
} 
 
bool B_SPLine::GetBSPLine(float u, ControlPoint *result) 
{ 
	int i; 
	float *pN; 
	float tmpx,tmpy; 
	 
	std::list<ControlPoint>::iterator iter; 
	//获取u所在区间 
	GetURegion(u); 
	//清零结果结构体中的所有变量值 
	tmpx=0; 
	tmpy=0; 
	//根据u更新所有有关的B样条基函数 
	CalcNiku(u); 
	//计算B样条曲线对应于u的值 
	i=(m_K+1)*m_K/2; 
	pN=m_Niku+i; 
 
	if(m_LowerBoundIdx>=m_K) 
	{ 
		for(iter=m_ControlPoints.begin(),i=0;i<m_LowerBoundIdx-m_K;++i,++iter) 
		{ 
			; 
		} 
		for(i=0;i<=m_K;++i,++iter) 
		{ 
			tmpx+=iter->point.x*pN[m_K-i]; 
			tmpy+=iter->point.y*pN[m_K-i]; 
			//printf("(%f,%f)-",tmpx,tmpy); 
		} 
	} 
	else 
	{ 
		pN=pN+m_K; 
		for(iter=m_ControlPoints.end(),i=m_K-m_LowerBoundIdx;i>0;i--) 
		{ 
			--iter; 
		} 
		for(;iter!=m_ControlPoints.end();++iter) 
		{ 
			tmpx+=iter->point.x**pN; 
			tmpy+=iter->point.y**pN; 
			--pN; 
		} 
		for(iter=m_ControlPoints.begin(),i=0;i<=m_LowerBoundIdx;++iter,++i) 
		{ 
			tmpx+=iter->point.x**pN; 
			tmpy+=iter->point.y**pN; 
			--pN; 
		} 
	} 
	result->point.x=tmpx; 
	result->point.y=tmpy; 
	//getchar(); 
	return TRUE;	 
} 
 
void B_SPLine::CalcNiku(float u) 
{ 
	int k,l; 
	float *pN; 
	float tmp1,tmp2; 
	int N; 
 
	N=m_ControlPoints.size(); 
	 
	pN=m_Niku; 
	*pN=1; 
	++pN; 
	for(k=1;k<=m_K;++k) 
	{ 
		for(l=0;l<=k;++l) 
		{ 
			if(l==0) 
			{ 
				tmp1=GetNiku(0,k-1); 
				*pN=(u-m_LowerBound)/k/m_DeltaU*tmp1; 
			} 
			else if(l==k) 
			{ 
				tmp1=GetNiku(l-1,k-1); 
				*pN=(m_UpperBound-u)/k/m_DeltaU*tmp1; 
			} 
			else 
			{ 
				tmp1=GetNiku(l,k-1); 
				tmp2=GetNiku(l-1,k-1); 
				*pN=(u-m_LowerBound+l*m_DeltaU)*tmp1+(m_UpperBound+(k-l)*m_DeltaU-u)*tmp2; 
				tmp1=k*m_DeltaU; 
				*pN/=tmp1; 
			} 
			//printf("l--%d,k--%d,%f\n",l,k,*pN); 
			//getchar(); 
			++pN; 
		} 
	} 
} 
 
 
B_SPLine::B_SPLine(int k) 
{ 
	int tmp; 
	m_K=k; 
	tmp=(k+1)*(k+2)/2; 
	m_Niku=new float[tmp]; 
} 
 
B_SPLine::~B_SPLine() 
{ 
	m_ControlPoints.clear(); 
	delete [] m_Niku; 
} 
 
float B_SPLine::GetNiku(int l, int k) 
{ 
	//索引为(l,k)----(0,0),(0,1),(1,1)... 
	if(k>m_K||l>k) 
		return 0; 
	int tmp; 
	float *p; 
	p=m_Niku; 
	tmp=k*(k+1)/2; 
	p=p+tmp; 
	return *(p+l); 
} 
 
 
void MouseCallback(int mouseEvent, int x, int y, int flags, void *param) 
{ 
	ControlPoint cp; 
	unsigned char *p; 
	mouseParam *mouseparam; 
 
	mouseparam=(mouseParam *)param; 
	switch(mouseEvent) 
	{ 
	case CV_EVENT_LBUTTONDOWN:				//输入一个控制点 
		cp.point=cvPoint(x,y); 
		mouseparam->pclass->m_ControlPoints.push_back(cp); 
		p=(unsigned char *)(mouseparam->img->imageData+x*mouseparam->img->nChannels+y*mouseparam->img->widthStep); 
		*p=255; 
		break; 
	//case CV_EVENT_LBUTTONDBLCLK:			//控制点输入完毕 
	//	mouseparam->pclass->DrawBSPLine(mouseparam->img); 
	//	break; 
	case CV_EVENT_RBUTTONDOWN:				//清空图片 
		mouseparam->pclass->m_ControlPoints.clear(); 
		cvZero(mouseparam->img); 
		break; 
	default: 
		break; 
	} 
}