ApproxChains
用多邊形曲線逼近 Freeman 鏈
CvSeq* cvApproxChains( CvSeq* src_seq, CvMemStorage* storage, int method=CV_CHAIN_APPROX_SIMPLE, double parameter=0, int minimal_perimeter=0, int recursive=0 );
- src_seq
- 涉及其它鏈的鏈指針
- storage
- 存儲多邊形線段位置的緩存
- method
- 逼近方法 (見函數 cvFindContours的描述).
- parameter
- 方法參數(現在不用).
- minimal_perimeter
-
僅逼近周長大於
minimal_perimeter
輪廓。其它的鏈從結果中除去。 - recursive
-
如果非 0, 函數從
src_seq
中利用h_next
和v_next links
連接逼近所有可訪問的鏈。如果為 0, 則僅逼近單鏈。
這是一個單獨的逼近程序。 對同樣的逼近標識,函數 cvApproxChains 與 cvFindContours 的工作方式一模一樣。它返回發現的第一個輪廓的指針。其它的逼近模塊,可以用返回結構中的 v_next
和 v_next
域來訪問
StartReadChainPoints
初始化鏈讀取
void cvStartReadChainPoints( CvChain* chain, CvChainPtReader* reader );
-
chain
鏈的指針
reader
鏈的讀取狀態
函數 cvStartReadChainPoints 初始化一個特殊的讀取器 (參考 Dynamic Data Structures以獲得關於集合與序列的更多內容).
ReadChainPoint
得到下一個鏈的點
CvPoint cvReadChainPoint( CvChainPtReader* reader );
- reader
- 鏈的讀取狀態
函數 cvReadChainPoint返回當前鏈的點,並且更新讀取位置。
ApproxPoly
用指定精度逼近多邊形曲線
CvSeq* cvApproxPoly( const void* src_seq, int header_size, CvMemStorage* storage, int method, double parameter, int parameter2=0 );
- src_seq
- 點集數組序列
- header_size
- 逼近曲線的頭尺寸
- storage
- 逼近輪廓的容器。如果為 NULL, 則使用輸入的序列
- method
-
逼近方法。目前僅支持
CV_POLY_APPROX_DP
, 對應 Douglas-Peucker 算法. - parameter
-
方法相關參數。對
CV_POLY_APPROX_DP
它是指定的逼近精度 - parameter2
-
如果
src_seq
是序列,它表示要么逼近單個序列,要么在src_seq
的同一個或低級層次上逼近所有序列 (參考 cvFindContours 中對輪廓繼承結構的描述). 如果src_seq
是點集的數組 ( CvMat*) , 參數指定曲線是閉合 (parameter2
!=0) 還是非閉合 (parameter2
=0).
函數 cvApproxPoly逼近一個或多個曲線,並返回逼近結果。對多個曲線的逼近,生成的樹將與輸入的具有同樣的結構。(1:1 的對應關系).
BoundingRect
計算點集的最外面(up-right)矩形邊界
CvRect cvBoundingRect( CvArr* points, int update=0 );
- points
-
二維點集,點的序列或向量 (
CvMat
) - update
-
更新標識。下面是輪廓類型和標識的一些可能組合:
- update=0, contour ~ CvContour*: 不計算矩形邊界,但直接由輪廓頭的
rect
域得到。 - update=1, contour ~ CvContour*: 計算矩形邊界,而且將結果寫入到輪廓頭的
rect
域中 header. - update=0, contour ~ CvSeq* or CvMat*: 計算並返回邊界矩形
- update=1, contour ~ CvSeq* or CvMat*: 產生運行錯誤 (runtime error is raised)
- update=0, contour ~ CvContour*: 不計算矩形邊界,但直接由輪廓頭的
函數 cvBoundingRect返回二維點集的最外面 (up-right)矩形邊界。
ContourArea
計算整個輪廓或部分輪廓的面積
double cvContourArea( const CvArr* contour, CvSlice slice=CV_WHOLE_SEQ );
- contour
- 輪廓 (定點的序列或數組).
- slice
- 感興趣輪廓部分的起始點,缺省是計算整個輪廓的面積。
函數 cvContourArea計算整個輪廓或部分輪廓的面積。 對后面的情況,面積表示輪廓部分和起始點連線構成的封閉部分的面積。如下圖所示:
NOTE: 輪廓的方向影響面積的符號。因此函數也許會返回負的結果。應用函數 fabs()
得到面積的絕對值。
ArcLength
計算輪廓周長或曲線長度
double cvArcLength( const void* curve, CvSlice slice=CV_WHOLE_SEQ, int is_closed=-1 );
- curve
- 曲線點集序列或數組
- slice
- 曲線的起始點,缺省是計算整個曲線的長度
- is_closed
-
表示曲線是否閉合,有三種情況:
- is_closed=0 - 假設曲線不閉合
- is_closed>0 - 假設曲線閉合
- is_closed<0 - 若曲線是序列,檢查 ((CvSeq*)curve)->flags 中的標識 CV_SEQ_FLAG_CLOSED 來確定曲線是否閉合。否則 (曲線由點集的數組 (CvMat*) 表示) 假設曲線不閉合。
函數 cvArcLength通過依次計算序列點之間的線段長度,並求和來得到曲線的長度。
CreateContourTree
創建輪廓的繼承表示形式
CvContourTree* cvCreateContourTree( const CvSeq* contour, CvMemStorage* storage, double threshold );
- contour
- 輸入的輪廓
- storage
- 輸出樹的容器
- threshold
- 逼近精度
函數 cvCreateContourTree 為輸入輪廓 contour
創建一個二叉樹,並返回樹根的指針。如果參數 threshold
小於或等於 0 ,則函數創建一個完整的二叉樹。如果 threshold
大於 0 , 函數用 threshold
指定的精度創建二叉樹:如果基線的截斷區域頂點小於threshold,該數就停止生長並作為函數的最終結果返回。
ContourFromContourTree
由樹恢復輪廓
CvSeq* cvContourFromContourTree( const CvContourTree* tree, CvMemStorage* storage, CvTermCriteria criteria );
- tree
- 輪廓樹
- storage
- 重構的輪廓容器
- criteria
- 停止重構的准則
函數 cvContourFromContourTree 從二叉樹恢復輪廓。參數 criteria
決定了重構的精度和使用樹的數目及層次。所以它可建立逼近的輪廓。 函數返回重構的輪廓。
MatchContourTrees
用樹的形式比較兩個輪廓
double cvMatchContourTrees( const CvContourTree* tree1, const CvContourTree* tree2, int method, double threshold );
- tree1
- 第一個輪廓樹
- tree2
- 第二個輪廓樹
- method
-
相似度。僅支持
CV_CONTOUR_TREES_MATCH_I1
。 - threshold
- 相似度閾值
函數 cvMatchContourTrees 計算兩個輪廓樹的匹配值。從樹根開始通過逐層比較來計算相似度。如果某層的相似度小於 threshold
, 則中斷比較過程,且返回當前的差值。
計算幾何
MaxRect
對兩個給定矩形,尋找矩形邊界
CvRect cvMaxRect( const CvRect* rect1, const CvRect* rect2 );
- rect1
- 第一個矩形
- rect2
- 第二個矩形
函數 cvMaxRect尋找包含兩個輸入矩形的具有最小面積的矩形邊界。
CvBox2D
旋轉的二維盒子
typedef struct CvBox2D { CvPoint2D32f center; CvSize2D32f size; float angle; } CvBox2D;
BoxPoints
尋找盒子的頂點
void cvBoxPoints( CvBox2D box, CvPoint2D32f pt[4] );
- box
- 盒子
- pt
- 頂點數組
函數 cvBoxPoints計算輸入的二維盒子的定點。下面是函數代碼:
void cvBoxPoints( CvBox2D box, CvPoint2D32f pt[4] ) { float a = (float)cos(box.angle)*0.5f; float b = (float)sin(box.angle)*0.5f; pt[0].x = box.center.x - a*box.size.height - b*box.size.width; pt[0].y = box.center.y + b*box.size.height - a*box.size.width; pt[1].x = box.center.x + a*box.size.height - b*box.size.width; pt[1].y = box.center.y - b*box.size.height - a*box.size.width; pt[2].x = 2*box.center.x - pt[0].x; pt[2].y = 2*box.center.y - pt[0].y; pt[3].x = 2*box.center.x - pt[1].x; pt[3].y = 2*box.center.y - pt[1].y; }
FitEllipse
二維點集的橢圓擬合
CvBox2D cvFitEllipse2( const CvArr* points );
- points
- 點集的序列或數組
函數 cvFitEllipse 對給定的一組二維點集作橢圓的最佳擬合(最小二乘意義上的)。返回的結構與 cvEllipse 中的意義類似,除了 size
表示橢圓軸的整個長度,而不是一半長度。
FitLine
2D 或 3D 點集的直線擬合
void cvFitLine( const CvArr* points, int dist_type, double param, double reps, double aeps, float* line );
- points
- 2D 或 3D 點集,32-比特整數或浮點數坐標
- dist_type
- 擬合的距離類型 (見討論).
- param
- 對某些距離的數字參數,如果是 0, 則選擇某些最優值
- reps, aeps
- 半徑 (坐標原點到直線的距離) 和角度的精度,一般設為0.01。
- line
-
輸出的直線參數。2D 擬合情況下,它是包含 4 個浮點數的數組
(vx, vy, x0, y0),其中
(vx, vy)
是線的單位向量而(x0, y0)
是線上的某個點. 對 3D 擬合,它是包含 6 個浮點數的數組(vx, vy, vz, x0, y0, z0),
其中(vx, vy, vz)
是線的單位向量,而(x0, y0, z0)
是線上某點。
函數 cvFitLine 通過求 sumiρ(ri) 的最小值方法,用 2D 或 3D 點集擬合直線,其中 ri是第 i 個點到直線的距離, ρ(r) 是下面的距離函數之一:
dist_type=CV_DIST_L2 (L2
): ρ(r)=r2
/2 (最簡單和最快的最小二乘法) dist_type=CV_DIST_L1 (L1
): ρ(r)=r dist_type=CV_DIST_L12 (L1
-L2
): ρ(r)=2•[sqrt(1+r2
/2) - 1] dist_type=CV_DIST_FAIR (Fair): ρ(r)=C2
•[r/C - log(1 + r/C)], C=1.3998 dist_type=CV_DIST_WELSCH (Welsch): ρ(r)=C2
/2•[1 - exp(-(r/C)2
)], C=2.9846 dist_type=CV_DIST_HUBER (Huber): ρ(r)= r2
/2, if r < C C•(r-C/2), otherwise; C=1.345
ConvexHull2
發現點集的凸外形
CvSeq* cvConvexHull2( const CvArr* input, void* hull_storage=NULL, int orientation=CV_CLOCKWISE, int return_points=0 );
- points
- 2D 點集的序列或數組,32-比特整數或浮點數坐標
- hull_storage
- 輸出的數組(CvMat*) 或內存緩存 (CvMemStorage*),用以存儲凸外形。 如果是數組,則它應該是一維的,而且與輸入的數組/序列具有同樣數目的元素。輸出時修改頭使得數組裁減到外形的尺寸。輸出時,通過修改頭結構將數組裁減到凸外形的尺寸。
- orientation
-
凸外形的旋轉方向: 逆時針或順時針 (
CV_CLOCKWISE
orCV_COUNTER_CLOCKWISE
) - return_points
-
如果非零,點集將以外形 (hull) 存儲,而不是
hull_storage
為數組情況下的頂點形式 (indices) 以及hull_storag
為內存存儲模式下的點集形式(points)。
函數 cvConvexHull2 使用 Sklansky 算法計算 2D 點集的凸外形。如果 hull_storage
是內存存儲倉, 函數根據 return_points
的值,創建一個包含外形的點集或指向這些點的指針的序列。
例子. 由點集序列或數組創建凸外形
#include "cv.h" #include "highgui.h" #include <stdlib.h> #define ARRAY 0 void main( int argc, char** argv ) { IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 ); cvNamedWindow( "hull", 1 ); #if !ARRAY CvMemStorage* storage = cvCreateMemStorage(); #endif for(;;) { int i, count = rand()0 + 1, hullcount; CvPoint pt0; #if !ARRAY CvSeq* ptseq = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour), sizeof(CvPoint), storage ); CvSeq* hull; for( i = 0; i < count; i++ ) { pt0.x = rand() % (img->width/2) + img->width/4; pt0.y = rand() % (img->height/2) + img->height/4; cvSeqPush( ptseq, &pt0 ); } hull = cvConvexHull2( ptseq, 0, CV_CLOCKWISE, 0 ); hullcount = hull->total; #else CvPoint* points = (CvPoint*)malloc( count * sizeof(points[0])); int* hull = (int*)malloc( count * sizeof(hull[0])); CvMat point_mat = cvMat( 1, count, CV_32SC2, points ); CvMat hull_mat = cvMat( 1, count, CV_32SC1, hull ); for( i = 0; i < count; i++ ) { pt0.x = rand() % (img->width/2) + img->width/4; pt0.y = rand() % (img->height/2) + img->height/4; points[i] = pt0; } cvConvexHull2( &point_mat, &hull_mat, CV_CLOCKWISE, 0 ); hullcount = hull_mat.cols; #endif cvZero( img ); for( i = 0; i < count; i++ ) { #if !ARRAY pt0 = *CV_GET_SEQ_ELEM( CvPoint, ptseq, i ); #else pt0 = points[i]; #endif cvCircle( img, pt0, 2, CV_RGB( 255, 0, 0 ), CV_FILLED ); } #if !ARRAY pt0 = **CV_GET_SEQ_ELEM( CvPoint*, hull, hullcount - 1 ); #else pt0 = points[hull[hullcount-1]]; #endif for( i = 0; i < hullcount; i++ ) { #if !ARRAY CvPoint pt = **CV_GET_SEQ_ELEM( CvPoint*, hull, i ); #else CvPoint pt = points[hull[i]]; #endif cvLine( img, pt0, pt, CV_RGB( 0, 255, 0 )); pt0 = pt; } cvShowImage( "hull", img ); int key = cvWaitKey(0); if( key == 27 ) // 'ESC' break; #if !ARRAY cvClearMemStorage( storage ); #else free( points ); free( hull ); #endif } }
CheckContourConvexity
測試輪廓的凸性
int cvCheckContourConvexity( const CvArr* contour );
- contour
- 被測試輪廓 (點序列或數組).
函數 cvCheckContourConvexity輸入的輪廓是否為凸的。必須是簡單輪廓,比如沒有自交叉。
CvConvexityDefect
用來描述一個簡單輪廓凸性缺陷的結構體
typedef struct CvConvexityDefect { CvPoint* start; CvPoint* end; CvPoint* depth_point; float depth; } CvConvexityDefect;
Picture. Convexity defects of hand contour.
ConvexityDefects
發現輪廓凸形缺陷
CvSeq* cvConvexityDefects( const CvArr* contour, const CvArr* convexhull, CvMemStorage* storage=NULL );
- contour
- 輸入輪廓
- convexhull
-
用
cvConvexHull2 得到的凸外形,它應該包含輪廓的定點或下標,而不是外形點的本身,即
cvConvexHull2 中的參數
return_points
應該設置為 0. - storage
- 凸性缺陷的輸出序列容器。如果為 NULL, 使用輪廓或外形的存儲倉。
函數 cvConvexityDefects 發現輸入輪廓的所有凸性缺陷,並且返回 CvConvexityDefect結構序列。
MinAreaRect2
對給定的 2D 點集,尋找最小面積的包圍矩形
CvBox2D cvMinAreaRect2( const CvArr* points, CvMemStorage* storage=NULL );
- points
- 點序列或點集數組
- storage
- 可選的臨時存儲倉
函數 cvMinAreaRect2通過建立凸外形並且旋轉外形以尋找給定 2D 點集的最小面積的包圍矩形.
Picture. Minimal-area bounding rectangle for contour
MinEnclosingCircle
對給定的 2D 點集,尋找最小面積的包圍圓形
int cvMinEnclosingCircle( const CvArr* points, CvPoint2D32f* center, float* radius );
- points
- 點序列或點集數組
- center
- 輸出參數:圓心
- radius
- 輸出參數:半徑
函數 cvMinEnclosingCircle對給定的 2D 點集迭代尋找最小面積的包圍圓形。如果產生的圓包含所有點,返回非零。否則返回零(算法失敗)。
CalcPGH
計算輪廓的 pair-wise 幾何直方圖
void cvCalcPGH( const CvSeq* contour, CvHistogram* hist );
- contour
- 輸入輪廓,當前僅僅支持具有整數坐標的點集
- hist
- 計算出的直方圖,必須是兩維的。
函數 cvCalcPGH 計算輪廓的 2D pair-wise(Hunnish: 不知如何翻譯,只好保留) 幾何直方圖 (pair-wise geometrical histogram :PGH), 算法描述見 [Iivarinen97]. 算法考慮的每一對輪廓邊緣。計算每一對邊緣之間的夾角以及最大最小距離。具體做法是,輪流考慮每一個邊緣做為基准,函數循環遍歷所有邊緣。在考慮基准邊緣和其它邊緣的時候, 選擇非基准線上的點到基准線上的最大和最小距離。邊緣之間的角度定義了直方圖的行,而在其中增加對應計算出來的最大和最小距離的所有直方塊, (即直方圖是 [Iivarninen97] 定義中的轉置). 該直方圖用來做輪廓匹配。