2011年12月22日星期四

椭圆拟合

#include "cv.h"
#include "highgui.h"


int slider_pos=70;//阈值


IplImage *image02 =0,*image03 = 0,*image04 = 0;
void process_image(int h);


int main(int argc ,char **argv)
{
const char *filename ="rice.png";
if ((image03 = cvLoadImage(filename,0))==0)//读入图像为灰度图像
{
return -1;
}
image02 = cvCloneImage(image03);
image04 = cvCloneImage(image03);


cvNamedWindow("Source",1);
cvNamedWindow("Result",1);


cvShowImage("Source",image03);


cvCreateTrackbar("Threshold","Result",&slider_pos,255,process_image);


process_image(0);


cvWaitKey(0);
cvSaveImage("1.jpg",image04);


cvReleaseImage(&image02);
cvReleaseImage(&image03);


cvDestroyWindow("Source");
cvDestroyWindow("Result");
return 0;


}


//这个函数寻找出轮廓、用椭圆拟合画出
void process_image(int h)
{
CvMemStorage *stor;
CvSeq *cont;
CvBox2D32f *box;
CvPoint *PointArray;
CvPoint2D32f *PointArray2D32f;


stor = cvCreateMemStorage(0);
cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT,sizeof(CvSeq),sizeof(CvPoint),stor);


cvThreshold(image03,image02,slider_pos,255,CV_THRESH_BINARY);


cvFindContours(image02,stor,&cont,sizeof(CvContour),
CV_RETR_LIST,CV_CHAIN_APPROX_NONE,cvPoint(0,0));


cvZero(image02);
cvZero(image04);


//绘制所有轮廓并用椭圆拟合
for (;cont;cont = cont ->h_next)
{
int i;
int count= cont->total;//轮廓个数
CvPoint center;
CvSize size;


/*个数必须大于6,这是cvFitEllipse_32f的要求*/
if (count<6) { continue; } //分配内存给点集 PointArray = (CvPoint *)malloc(count*sizeof(CvPoint)); PointArray2D32f = (CvPoint2D32f*)malloc(count*sizeof(CvPoint2D32f)); //分配内存给椭圆数据 box = (CvBox2D32f *)malloc(sizeof(CvBox2D32f)); //得到点集(这个方法值得借鉴) cvCvtSeqToArray(cont,PointArray,CV_WHOLE_SEQ); //将CvPoint点集转化为CvBox2D32f集合 for (i=0;icenter.x);
center.y = cvRound(box->center.y);
size.width = cvRound(box->size.width*0.5);
size.height = cvRound(box->size.height*0.5);
box->angle = -box->angle;

//画椭圆
cvEllipse(image04,center,size,box->angle,0,360,CV_RGB(0,0,255),1,CV_AA,0);

free(PointArray);
free(PointArray2D32f);
free(box);
}
cvShowImage("Result",image04);
}

CString, TCHAR, char* 的转换

CString, TCHAR, char* 的转换
转自:http://bboytaiwan.spaces.live.com/blog/cns!F712BFEC83D26022!975.entry




ANSI to Unicode:
--------------------------------------------------
char *pAnsiString = "Some test string";
CString strUnicode = pAnsiString;
---------------------------------------------------




如何把 char 转为lpctstr
mbstowcs---Convert a multi-byte(ANSI) string to wide character stirng(Unicode).
wcstombs---Convert a wide character string to multi-byte string.
--------------------------------------------------




cstring TCHAR的互相转换


cstring->TCHAR*的转化可以用函数GetBuff()
函数原型为:LPTSTR GetBuffer( int nMinBufLength );
cstring str("cstring");
TCHAR* szMsg = new TCHAR[100];
//其参数为cstring字符串的长度
szMsg = str.GetBuffer(str.GetLength());
str.ReleaseBuffer();
delete []szMsg;
szMsg = NULL;
TCHAR*->cstring的转化
TCHAR szTchar[18] = L"TCHAR";
cstring str;
str.Format(_T("%s"),szTchar);
-------------------------------------------------------------




Unicode to ANSI:


char* GetAnsiString(const CString &s)
{
int nSize = s.GetLength();
char *pAnsiString = new char[nSize+1];
wcstombs(pAnsiString, s, nSize+1);
return pAnsiString;
}
CString strUnicode = _T("Some test string");
char *pAnsiString = GetAnsiString(strUnicode);




注1:在上面例子中使用了wcstombs(pAnsiString, s, nSize+1);
程序编译时会提示:
warning C4996: 'wcstombs': This function or variable may be unsafe. Consider using wcstombs_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
而且上面的GetAnsiString函数似乎也有问题:返回了局域指针。因为我建立的是unicode工程,所以将上面函数改为:
string GetAnsiString(const wchar_t *s)
{
int iLength = (int)wcslen( s ) + 1;
const int size = 100;
char ansistring[size];
size_t iConverted = 0;
wcstombs_s( &iConverted, ansistring, iLength, s, _TRUNCATE );


return string(ansistring);
}
CString strUnicode = _T("Some test string");
string ansiString = GetAnsiString(strUnicode);




注2:关于ANSI和Unicode的关系,详见《VC++的Unicode编程》