【OpenCV学习笔记】【函数学习】十四(cvSeq的用法说明(功能很多,按照需求使用))



 OpenCV CvSeq 结构
一直困惑于CvSeq到底是个什么样的东西,因为曾经拿到别人写的一个函数库,其返回值是一个CvSeq指针,我的任务是遍历所有的Sequence,然后删除其中不符合要求的Sequence。由于没有文档,我当时并不知道我需要遍历的是
Sequence还是Sequence中的Element。于是我写下了类似如下的代码:
CvSeq *pCurSeq = pInputSeq;
int index = 0;
while( pCurSeq=pCurSeq->h_next )
{
if( process(pCurSeq) )
{
pCurSeq = pCurSeq->h_prev; //这里为了简单不考虑是否为列表头
cvSeqRemove(pInputSeq, index);
--index;
}
++index;
}

事实证明这段代码是错误的,而且往往返回的错误信息是
> OpenCV ERROR: One of arguments' values is out of range (Invalid index)
> in function cvSeqRemove, cxdatastructs.cpp(1587)



为什么会有这样的错误呢?看一下CvSeq的源代码就可略见一斑。下面是OpenCV1.0版本有关CvSeq的定义
#define CV_TREE_NODE_FIELDS(node_type) \
int flags; \
int header_size; \
struct node_type* h_prev; \
struct node_type* h_next; \
struct node_type* v_prev; \
struct node_type* v_next

#define CV_SEQUENCE_FIELDS() \
CV_TREE_NODE_FIELDS(CvSeq); \
int total; \
int elem_size; \
char* block_max; \
char* ptr; \
int delta_elems; \
CvMemStorage* storage; \
CvSeqBlock* free_blocks; \
CvSeqBlock* first;


typedef struct CvSeq
{
CV_SEQUENCE_FIELDS()
}
CvSeq;

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

后来在Google Book里查了一下,发现《Learning OpenCV:Computer Vision with the OpenCV Library》中有这么一段话描述的不错:
The sequence structure itself has some important elements that you should be aware of. The first, and one you will use often, is total. This is the total number of points or objects in the sequence. The next four important elements are pointers to other sequence: h_prev, h_next, v_prev and v_next. These four pointers are part of what are called CV_TREE_NODE_FIELDS; they are used not to indicate elements inside of the sequence but rather to connect different sequences to one another. Other objects in the OpenCV universe also contain these tree node fields.
OpenCV中的数据结构CvSeq(序列)
OpenCV中的基本数据结构 —-  序列:
动态结构序列CvSeq是所有OpenCv动态数据结构的基础。有两种类型的序列:稠密序列,稀疏序列:
(1) 稠密序列都派生自CvSeq,他们用来代表可扩展的一维数组 — 向量、栈、队列和双端队列。数据间不存在空隙(连续存储)。如果元素元素从序列中间被删除或插入新的元素到序列,那么此元素后边的相关元素全部被移动。
(2)稀疏序列派生自CvSet,CvSet也是基于CvSeq的,他们都是由节点所组成,每一个节点要么被占用,那么为空,由标志位flag决定。这些序列作为无序数据结构被使用,如点集合、图、Hash表等。
结构CvSeq的具体定义如下:

#define CV_SEQUENCE_FIELDS()                                              \
    CV_TREE_NODE_FIELDS(CvSeq);                                           \
    int       total;            \\Total number of elements.
    int       elem_size;        \\Size of sequence element in bytes.
    schar*    block_max;        \\Maximal bound of the last block.
    schar*    ptr;              \\Current write pointer.
    int       delta_elems;      \\Grow seq this many at a time.
    CvMemStorage* storage;      \\Where the seq is stored.
    CvSeqBlock* free_blocks;    \\Free blocks list. 
    CvSeqBlock* first;         \\Pointer to the first sequence block.
 
typedef struct CvSeq
{
    CV_SEQUENCE_FIELDS()
}
CvSeq;

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

转自:openCV中 cvSeq的用法说明

相关博文:OpenCV中如何剔除检测到的不符合要求的对象

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值