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)矩:

image.png

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
);

image.png

image.png

使用Hu 矩进行匹配

double cvMatchShapes(
    const void* object1,
    const void* object2,
    int method,
    double parameter = 0
);

1569510602774125.png

1569510671548009.png

等级匹配

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 C/C++
相关文章
评论留言
发布留言