OpenCV 轮廓
一、内存
访问内存存储器的四个函数:
CvMemStorage* cvCreateMemStorage( int block_size = 0 ); void cvReleaseMemStorage( CvMemStorage** storage ); void cvClearMemStorage( CvMemStorage* storage ); void * cvMemStorageAlloc( CvMemStorage* storage, size_t size );
block_size : =0,表示内存块采用默认的大小,默认大小为64KB。
二、序列
序列CvSeq的定义
typedef struct CvSeq ( int flags; // miscellaneous flags int header_size; // size of sequence header CvSeq* h_prev; CvSeq* h_next; CvSeq* v_prev; CvSeq* v_next; int total; int elem_size; char* block_max; char* ptr; int delta_elems; CvMemStorage* storage; CvSeqBlock* free_blocks; CvSeqBlock* first; }
创建序列
CvSeq* cvCreateSeq( int seq_flags, int header_size, int elem_size, CvMemStorage* storage );
flags变量可由3个类值组成:
# 第一类确定序列中元素的类型 CV_SEQ_ELTYPE_POINT 点坐标:(x,y) CV_SEQ_ELTYPE_CODE Freeman:0..7 CV_SEQ_ELTYPE_PPOINT 指向一个点的指针:&(x,y) CV_SEQ_ELTYPE_INDEX 点的整数索引:#(x,y) CV_SEQ_ELTYPE_GRAPH_EDGE &next_o, &next_d, &vtx_o, &vtx_d CV_SEQ_ELTYPE_GRAPH_VERTEX first_edge, &(x,y) CV_SEQ_ELTYPE_TRIAN_ATR 二叉树的节点 CV_SEQ_ELTYPE_CONECTED_COMP 联通的区域 CV_SEQ_ELTYPE_POINT3D 三维的点坐标:(x,y,z) # 第二类表示序列本身的性质 CV_SEQ_KIND_SET 元素的集合 CV_SEQ_KIND_CURVE 元素所定义的曲线 CV_SEQ_KIND_BIN_TREE 二叉树 CV_SEQ_KIND_GRAPH 图,其节点为序列内元素 # 第三类表示序列的其他属性 CV_SEQ_FLAG_CLOSED 序列是闭合的(多边形) CV_SEQ_FLAG_SIMPLE 序列是简单的(多边形) CV_SEQ_FLAG_CONVEX 序列是凸的(多边形) CV_SEQ_FLAG_HOLE 序列是一个嵌套的(多边形)
删除序列
void cvClearSeq( CvSeq* seq );
直接访问序列中的元素
char* cvGetSeqElem(seq, index);
示例:
for(int i=0;i<seq->total; ++i) { CvPoint* p = (CvPoint*) cvGetSeqEle(seq,i); printf("(%d,%d)\n", p->x, p->y); )
检测元素
int cvSeqElemIdx( const CvSeq* seq, const void* element, CvSeqBlock** block = NULL );
切片、复制和移动序列中的数据
CvSeq* cvCloneSeq( const CvSeq* seq, CvMemStorage* storage = NULL ); CvSeq* cvSeqSlice( const CvSeq* seq, CvSlice slice, CvMemStorage* storage = NULL, int copy_data = 0 ); void cvSeqRemvoeSlice( CvSeq* seq, CvSlice slice ); void cvSeqInsertSlice( CvSeq* seq, int before_index, const CvArr* from_arr );
typedef int (*CvCmpFunc)(const void* a, const void* b, void* userdata);
void cvSeqSort( CvSeq* seq, CvCmpFunc func, void* userdata = NULL ); char * cvSeqSearch( CvSeq* seq, const void* elem, CvCmpFunc func, int is_sorted, int * elem_idx, void* userdata = NULL ); void cvSeqInvert( CvSeq* seq ); int cvSeqPartition( const CvSeq* seq, CvMemStorage* storage, CvSeq** labels, CvCmpFunc is_equal, void* userdata );
将序列作为栈来使用
插入和删除元素
序列中块的大小
void cvSetSeqBlockSize( CvSeq* seq, int delta_elems );
序列的读取和写入
序列和数组
void* cvCvtSeqToArray( const CvSeq* seq, void* elements, CvSlice slice = CV_WHOLE_SEQ ); CvSeq* cvMakeSeqHeaderForArray( int seq_type, int header_size, int elem_size, void* elements, int total, CvSeq* seq, CvSeqBlock* block );
查找轮廓
int cvFindContours( IplImage* img, CvMemStorage* storage, CvSeq** firstContour, int headerSize = sizeof(CvContour), CvContourRetrievalMode mode = CV_RETR_LIST, CvChainApproxMethod method = CV_CHAIN_APPROX_SIMPLE );
CV_RETR_EXTERNAL 只检测出最外的轮廓 CV_RETR_LIST 检出所有的轮廓并将他们保存到表中 CV_RETR_CCOMP 检出所有的轮廓并将他们组织成双层机构,顶层边界是所有成分的外界边界,第二层边界是空的边界。 CV_RETR_TREE 检出所有的轮廓并且重新建立网状的轮廓结构。
method 值
CV_CHAIN_CODE 用Freeman链码输出轮廓 CV_CHAIN_APPROX_NONE 将链码编码中的所有点转换为点 CV_CHAIN_APPROX_SIMPLE 压缩水平,垂直或斜的部分,只保存最后一个点 CV_CHAIN_APPROX_TC89_L1 \ CV_CHAIN_APPROX_TC89_KCOS 使用Teh-chin链逼近算法中的一个 CV_LINK_RUNS 连接所有的水平层次的轮廓,此方法只可与 CV_RETR_LIST 搭配使用
使用序列表示轮廓
int cvFindContours ( CvArr* img, CvMemStorage* storage, CvSeq** first_contour, int header_size = sizeof(CvContour), int mode = CV_RETR_LIST, int method = CV_CHAIN_APPROX_SIMPLE, CvPoint offset = cvPoint(0,0) ); CvContourScanner cvStartFindContours( CvArr* image, CvMemStorage* storage, int header_size = sizeof(CvContour), int mode = CV_RETR_LIST, int method = CV_CHAIN_APPROX_SIMPLE, CvPoint offset = cvPoint(0,0) ); CvSeq* cvFindNextContour( CvContourScanner scanner ); void scSubstituteContour( SvContourScanner scanner, SvSeq* new_contour ); CvSeq* cvEndFindContour( CvContourScanner* scanner ); CvSeq* cvApproxChains( CvSeq* src_seq, CvMemStorage* storage, int method = CV_CHAIN_APPROX_SIMPLE, double parameter = 0, int minial_perimeter = 0, int recursive = 0 );
Freeman链码
void cvStartReadChainPoints( CvChain* chain, CvChainPtReader* reader ); CvPoint cvReadChainPoint( CvChainPtReader* reader );
绘制轮廓
void cvDrawContours( CvArr* img, CvSeq* contour, CvScalar external_color, CvScalar hole_color, int max_level, int thickness = 1, int line_type = 8, CvPoint offset = cvPoint(0,0) );
深入分析轮廓
多边形逼近
CvSeq* cvApproxPoly( const void* src_seq, int header_size, CvMemStorage* storage, int method, double parameter, int recursive = 0 ); Cvseq* cvFindDominantPoints( CvSeq* contour, CvMemStorage* storage, int method = CV_MOMINANT_IPAN, double parameter1 = 0, double parameter2 = 0, double parameter3 = 0, double parameter4 = 0 );
特性概括
长度
double cvArcLength( const void* curve, CvSlice slice = CV_WHOLE_SEQ, int is_closed = -1 ); #define cvContourPerimeter( contour) \ cvArcLength(contour,CV_WHOLE_SEQ,1) double cvContourArea( const CvArr* contour, CvSlice slice = CV_WHOLE_SEQ );
边界框
CvRect cvBoundingRect( CvArr* points, int update = 0 ); CvBox2D cvMinAreaRect2( const CvArr* points, CvMemStorage* storage = NULL ); typedef struct CvBox2D ( CvPoint2D32f center; CvSize2D32f size; float angle; ) CvBOx2D;
圆形和椭圆形边界
int cvMinEnclosingCircle( const CvArr* points, CvPoints2D32f* center, float* radius ); CvBox2D cvFitEllipse2( const CvArr* points );
几何
在处理CvBox2D 或者多边形边界的时候,经常需要进行多边形以及边界框的重叠判断。
CvRect cvMaxRect( const CvRect* rect1, const CvRect* rect2 ); void cvBoxPoints( CvBox2D box, CvPoint2D32f pt[4] ); CvSeq* cvPointSeqFromMat( int seq_kind, const CvArr* mat, CvContour* contour_header, CvSeqBlock* block ); double cvPointPolygonTest( const CvArr* contour, CvPoint2D32f pt, int measure_dist );
轮廓的匹配
矩:通过对轮廓上所有点进行积分运算(或者认为是求和运算)而得到的一个粗略特征。
通常,我们如下定义一个轮廓的(p,q)矩:
void cvContoursMoments( CvSeq* contour, CvMoments* monents ); typedef struct CvMoments{ // spatial moments double m00,m10,m01,m20, m02, m30, m21, m12, m03; // central moments double mu11, mu11, mu02, mu21, mu12, mu03; // m00 != 0 ? 1/sqrt(m00):0 double inv_sqrt_m00; }CvMoments;
double cvGetSpatialMoment( CvMoments* moments, int x_order, int y_order );
再论矩
void cvMoments( const CvArr* image, CvMents* moments, int isBinary = 0 ) double cvGetCentralMoment( CvMoments* moments, int x_order, int y_order ) double cvGetNormalizeCentralMoment( CvMoments* moments, int x_order, int y_order ); void cvGetHuMoments( CvMoments* moments, CvHumoments* Humoments );
使用Hu 矩进行匹配
double cvMatchShapes( const void* object1, const void* object2, int method, double parameter = 0 );
等级匹配
CvContourTree* cvCreateContourTree( const CvSeq* contour, CvMemStorage* storage, double threshold ); CvSeq* cvContourFromControurTree( const CvContourTree* tree, CvMemStorage* storage, CvTermCriteria criteria ); double cvMatchContourTree( const CvContourTree* tree1, const CvContourTree* tree2, int method, double threshold );
CvTermCriteria termcrit = cvTermCriteria( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 5,1));
轮廓的凸包和凸缺陷
#define CV_CLOCKWISE 1 #define CV_COUNTER_CLOCKWISE 2 CvSeq* cvConverHull2( const CvArr* input, void* hull_storage = NULL, int orientation = CV_CLOCKWISE, int return_points = 0 ); int cvCheckContourConvexity( const CvArr* contour ); CvSeq* cvConvexityDefects( const CvArr* contour, const CvArr* convexhull, cvMemStorage* storage = NULL ); typedef struct CvConvexityDefect { // point of the contour where the defect begins CvPoint* start; // point of the contour where the defect ends CvPoint* end; // point within the defect farthest from the convex hull CvPoint* depth_point; // distance between the farthest point and the convex hull float depth; } CvConvexityDefect;
成对几何直方图
void cvCalcPGH( const CvSeq* contour, CvHistogram* hist );
- 上一篇:OpenCv 图像局部与分割
- 下一篇:OpenCV 直方图与匹配
相关文章
评论留言