今天原本想寫一個圖像橢圓擬合的,使用到opencv庫。主要想借助opencv裏的cvFindContours函數先獲得圖像中的全部輪廓,接着對每個contours->h_next 進行下面的一樣操做。contours這個變量是CvSeq 類型的,是opencv中一個基礎的動態庫。我本來打算將contours這個序列轉化獲得該輪廓各點所在的位置,即將contours 裝換成CvPoint 類型的變量,獲得輪廓全部的點以後好進一步對它們進行橢圓的擬合。擬合的函數是經過一個cvFitEllipse2(CvArr* points) 這個函數來的。當我直接將contours(CvSeq)做爲參數時,編譯器固然不給經過,畢竟接受的參數類型不一致。 可是想到opencv裏面有一個cvDrawContours 的函數,它的做用就是畫輪廓圖的。那麼,它在畫的時候,勢必要得到輪廓像素所在的位置,所以,就查找opencv源代碼,該函數在一個\src\cvcore\cxdrawing.cpp的文件中實現。實現以下: .......
while( (contour = (CvSeq*)cvNextTreeNode( &iterator )) != 0 ) { CvSeqReader reader; int i, count = contour->total; int elem_type = CV_MAT_TYPE(contour->flags); void* clr = (contour->flags & CV_SEQ_FLAG_HOLE) == 0 ? ext_buf : hole_buf;函數
cvStartReadSeq( contour, &reader, 0 ); if( thickness < 0 ) pts.resize(0); if( CV_IS_SEQ_CHAIN_CONTOUR( contour )) { cv::Point pt = ((CvChain*)contour)->origin; //!!!!!!!!這裏就是將contours轉換爲points的 cv::Point prev_pt = pt; char prev_code = reader.ptr ? reader.ptr[0] : '\0'; prev_pt += offset; for( i = 0; i < count; i++ ) { char code; CV_READ_SEQ_ELEM( code, reader ); assert( (code & ~7) == 0 ); if( code != prev_code ) { prev_code = code; if( thickness >= 0 ) cv::ThickLine( img, prev_pt, pt, clr, thickness, line_type, 2, 0 ); else pts.push_back(pt); prev_pt = pt; }
........code
上面標註的CvChain 結構在opencv的幫助文檔中並無找獲得,好吧,在代碼中繼續追蹤它的定義所在,CvChain 的結構定義以下:對象
typedef struct CvChain { CV_SEQUENCE_FIELDS() /這一部分的定義和CvSeq 結構的定義相同/ CvPoint origin; /!!!!此處的origin 變量就是輪廓開始的點/ } CvChain;繼承
所以從功能上來講,CvChain 結構不如說是CvSeq 」派生「來的(可是C中沒有面向對象的概念),但此處的定義與繼承或派生類似,姑且能夠這麼看吧。ip
固然,origin變量記錄的只是一條輪廓的開始位置,並不包含所有的輪廓像素的位置信息!要想獲取獲得所有位置,還得另想辦法。能想到的辦法就是利用種子生長類似的原理,使用8-鄰域對頭像素追宗,但彷佛花費稍微高了點。