CvSeq动态结构序列

本文深入解析了OpenCV中的动态数据结构CvSeq,包括稠密序列和稀疏序列的区别,以及CvSeq的具体定义和常用操作。通过示例代码展示了如何创建、复制、删除和排序序列,提供了对CvSeq基本概念和应用的全面理解。

原帖地址:http://blog.csdn.net/fulva/article/details/7395026

动态结构序列CvSeq是所有OpenCv动态数据结构的基础。有两种类型的序列:稠密序列,稀疏序列:

(1) 稠密序列都派生自CvSeq,他们用来代表可扩展的一维数组 — 向量、栈、队列和双端队列。数据间不存在空隙(连续存储)。如果元素元素从序列中间被删除或插入新的元素到序列,那么此元素后边的相关元素全部被移动。

(2)稀疏序列派生自CvSet,CvSet也是基于CvSeq的,他们都是由节点所组成,每一个节点要么被占用,那么为空,由标志位flag决定。这些序列作为无序数据结构被使用,如点集合、图、Hash表等。

结构CvSeq的具体定义如下:


[cpp]  view plain copy
  1. <span style="color:#ff0000; font-style:italic">/* 
  2.    Read/Write sequence. 
  3.    Elements can be dynamically inserted to or deleted from the sequence. 
  4. */</span>  
  5. <span style="color:#339900">#define CV_SEQUENCE_FIELDS()                                              \  
  6.     CV_TREE_NODE_FIELDS(CvSeq);                                           \  
  7.     int       total;          /* Total number of elements.            */  \  
  8.     int       elem_size;      /* Size of sequence element in bytes.   */  \  
  9.     schar*    block_max;      /* Maximal bound of the last block.     */  \  
  10.     schar*    ptr;            /* Current write pointer.               */  \  
  11.     int       delta_elems;    /* Grow seq this many at a time.        */  \  
  12.     CvMemStorage* storage;    /* Where the seq is stored.             */  \  
  13.     CvSeqBlock* free_blocks;  /* Free blocks list.                    */  \  
  14.     CvSeqBlock* first;        /* Pointer to the first sequence block. */</span>  
  15.    
  16. <span style="color:#00ff00">typedef</span> <span style="color:#00ff00">struct</span> CvSeq  
  17. <span style="color:#080000">{</span>  
  18.     CV_SEQUENCE_FIELDS<span style="color:#080000">(</span><span style="color:#080000">)</span>  
  19. <span style="color:#080000">}</span>  
  20. CvSeq<span style="color:#080800">;</span>  

 

total表示稠密序列的元素个数,或者稀疏序列被分配的节点数。elem_size表示序列中每个元素占用的字节数。block_max是最近一个内存的最大边界指针。ptr表示当写指针。delta_elems表示序列间隔尺寸。storage指向序列存储的内存块的指针。free_blocks表示空的块列表。first指向第一个序列块。


        CvSeq本身就是一个可增长的序列,CvSeq:total是指序列内部有效元素的个数;而h_next和h_prev并不是指向CvSeq内部元素的指针,它们是指向其它CvSeq的。再回到文章最初的代码,我们可以看到该代码具有逻辑上的错误,首先while语句遍历的是所有的CvSeq,使用process处理每一个CvSeq,而遇到需要删除的CvSeq时,又使用才cvSeqRemove删除当前CvSeq中的第index个元素。实际上此时index很可能超出了当前CvSeq中总元素的个数,所以出现了超出边界的错误。正确的做法是直接删除该CvSeq。


CvSeq* cvCreateSeq(int seq_flags,int header_size,int elem_size,CvMemStorage* storage)


功能:创建一序列 

参数:seq_flags为序列的符号标志。如果序列不会被传递给任何使用特定序列的函数,那么将它设为0,否则从预定义的序列类型中选择一合适的类型。Header_size为序列头部的大小;必须大于或等于sizeof(CvSeq)。如果制定了类型或它的扩展名,则此类型必须适合基类的头部大小。Elem_size为元素的大小,以字节计。这个大小必须与序列类型(由seq_flags指定)相一致。例如,对于一个点的序列,元素类型CV_SEQ_ELTYPE_POINT应当被指定,参数elem_size必须等同于sizeof(CvPoint)。Storage为指向前面定义的内存存储器


CvSeq* cvCloneSeq(const CvSeq* seq,CvMemStorage* storage=NULL)


功能:创建序列的一份拷贝



Void cvSeqInvert(CvSeq* seq)


功能:将序列中的元素进行逆序操作


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 cvClearSeq(CvSeq* seq);

功能:清空序列

Char* cvSeqPush(CvSeq* seq,void* element=NULL)

功能:添加元素到序列的尾部

void cvSeqPop(CvSeq* seq,void* element=NULL)

功能:删除序列尾部元素

Char* cvSeqPushFront(CvSeq* seq,void* element=NULL)

功能:在序列头部添加元素

Void cvSeqPopFront(CvSeq* seq,void* element=NULL)

功能:删除在序列的头部的元素

Void cvSeqPushMulti(CvSeq* seq,void* elements,int count,int in_front=0);

功能:添加多个元素到序列尾部或头部

Void cvSeqPopMulti(CvSeq* seq,void* elements,int count,int in_front=0)

功能:删除多个序列头部或尾部元素

Char* cvSeqInsert(CvSeq* seq,int before_index,void* element=NULL)

功能:在序列中的指定位置添加元素

Void cvSeqRemove(CvSeq* seq,int index)

功能:删除序列中的指定位置的元素

Char* cvGetSeqElem(const CvSeq* seq,int index)

功能:返回索引所指定的元素指针

Int cvSeqElemIdx(const CvSeq* seq,const void* element,CvSeqBlock** block=NULL)

功能:返回序列中元素的索引

Void cvStartAppendToSeq(CvSeq* seq,CvSeqWriter* writer)

功能:将数据写入序列中,并初始化该过程

Void cvStartWriteSeq(int seq_flags,int header_size,int elem_size,CvMemStorage* storage,CvSeqWriter* writer)

功能:创建新序列,并初始化写入部分

CvSeq* cvEndWriteSeq(CvSeqWriter* writer)

功能:完成写入操作

Void cvStartReadSeq(const CvSeq* seq,CvSeqReader* reader,int reverse=0)

功能:初始化序列中的读取过程

 

cvSeqSort函数详细说明

1、向seq容器添加一系列的CvPoint对象
2、定义cmp_func
3、调用cvSeqSort,该函数会在内部迭代seq,并每次从seq中取两个CvPoint对象出来作为a、b传入cmp_func,并且根据cmp_func的返回结果来调整这两个对象在seq中的相对位置,返回值是1,就调整序列元素位置。
 
  1. static int near_num_cmp(void* _a,void* _b,void* userdata )  
    {  
        pt_near* a =(pt_near*)_a;  
        pt_near* b =(pt_near*)_b;  
        return a->field_num>b->field_num ? -1 : a->field_num<b->field_num ? 1:0;  
    }  

cvSeqSort(pt_seq_a,(CvCmpFunc)near_num_cmp, 0);

//最终达到点的领域点数从大到小的排列

要达到小到大的顺序,只需将return a->field_num>b->field_num ? -1 : a->field_num<b->field_num ? 1:0;的>和<互换下

void cvSeqSort( CvSeq* seq, CvCmpFunc func, void* userdata=NULL );

seq

待排序的序列

func

比较函数,按照元素间的大小关系返回负数,零,正数(见:上面的声明和下面的例子) --相关函数为 C 运行时库中的 qsort, 后者(qsort)不使用参数userdata.

userdata

传递给比较函数的用户参数;有些情况下,可避免全局变量的使用

函数 cvSeqSort 使用特定的标准对序列进行排序。下面是一个使用该函数的实例

 

#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include "stdio.h"
#pragma comment(lib,"cv.lib")
#pragma comment(lib,"cxcore.lib")
#pragma comment(lib,"highgui.lib")

CvSeq* pointSort(CvSeq* seq);

void main()
{

CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* seq = cvCreateSeq( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
int i;

for( i = 0; i < 10; i++ )
{
    CvPoint pt;
    pt.x = rand();
    pt.y = rand();
    cvSeqPush( seq, &pt );
}
for( i = 0; i < seq->total; i++ )
{
    CvPoint* pt = (CvPoint*)cvGetSeqElem( seq, i );
    printf("( %d %d )\n",pt->x,pt->y );
}
printf("\n");
pointSort(seq);

/* print out the sorted sequence */
for( i = 0; i < seq->total; i++ )
{
    CvPoint* pt = (CvPoint*)cvGetSeqElem( seq, i );
    printf("( %d %d )\n",pt->x,pt->y );
}

cvReleaseMemStorage( &storage );
}
//cmp_func()函数的定义必须独立于其他函数定义
static int cmp_func( const void* _a, const void* _b, void* userdata )
{
CvPoint* a = (CvPoint*)_a;
CvPoint* b = (CvPoint*)_b;
int y_diff = a->y - b->y;
int x_diff = a->x - b->x;
//return x_diff ? x_diff : 0;
return y_diff ? y_diff :x_diff;//优先比交y坐标,a的y坐标大则调整a,b位置;否则比较x坐标,a的x坐标大,也调整a,b位置。
} //即交换a,b位置 swap(a,b) if (a->y >b->y)|(a->x >b->x)
CvSeq* pointSort(CvSeq* seq)
{

cvSeqSort( seq, cmp_func, 0 /* userdata is not used here */ );
return seq;
}

cvSeqSort函数详细说明 - jinlong_zhou_cool - 蓝梦

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值