openCV中 cvSeq的用法说明【转】

来源:互联网 发布:java io开销 编辑:程序博客网 时间:2024/05/29 03:10
1-06-10 15:14:41)
转载

openCV中 cvSeq的用法说

http://blog.csdn.net/wqvbjhc/archive/2010/04/17/5497017.aspx
--------------------------------------------------------------------------------

函数原型 说明
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)
 功能:初始化序列中的读取过程
 

OpenCV CvSeq的内部结构探讨
--------------------------------------------------------------------------------

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

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的源代码就可略见一斑。下面是OpenCV2.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;          // total number of elements             \  
    int       elem_size;      // size of sequence element in bytes    \  
    char*     block_max;      // maximal bound of the last block      \  
    char*     ptr;            // current write pointer        \  
    int       delta_elems;    // how many elements allocated when the seq grows   \  
    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;

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wqvbjhc/archive/2010/04/17/5497017.aspx

 
原来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;  
   }  

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.

参考:http://hi.baidu.com/ltbing/blog/item/490d88948af27c14d21b7008.html

      http://jackchongsun.blog.163.com/blog/static/4071607201019101312221/

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wqvbjhc/archive/2010/04/17/5497017.aspx

 

 //////////////////////////////////////////////////////////////////////////////////////////////

/////删除当前CvSeq,如果有下一个就指向下一个CvSeq,否则清空,此处要考虑多种情况,比如要删的是第一个、是最后一个、或是队列中就这一个

/////////////////////////////////////////////////////////////////////////////////////////////

void Delete_CvSeq(CvSeq* &contour_blackline)
{
 //删除此contour_blackline
 //CvSeq* contour_blackline=&contour_blackline_pt;
 if (!contour_blackline)
 {
  return;
 }
 CvSeq *pOldSeq = NULL;  
 pOldSeq = contour_blackline;  
 if(pOldSeq->h_prev)  
  
  if ( pOldSeq->h_next)
  {
   contour_blackline = pOldSeq->h_prev;  
   contour_blackline->h_next = pOldSeq->h_next;  
   pOldSeq->h_next->h_prev = contour_blackline;  
   contour_blackline=contour_blackline->h_next;  
   cvClearSeq( pOldSeq );
  }
  else
  {
   contour_blackline = pOldSeq->h_prev;
   contour_blackline->h_next=NULL;
   cvClearSeq( pOldSeq ); 
   contour_blackline = pOldSeq->h_next; 

  }

  
 else 
  
  if ( pOldSeq->h_next)
  {
   contour_blackline = pOldSeq->h_next;  
   contour_blackline->h_prev = NULL;  
   cvClearSeq( pOldSeq ); 

  }
  else
  {
   contour_blackline=NULL;
  }

 }

}

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 欧灵平板电脑忘记图密解锁怎么办 淘宝没货发给人被投诉了怎么办 淘宝店铺既不能开又不能注销怎么办 妻子被骗五万疑似被洗脑我该怎么办 奖虫账号和密码不匹配怎么办 开淘宝店余额宝里的钱怎么办 京东找不到所有宝贝的链接了怎么办 淘宝店链接改了标题没流量怎么办 淘宝手淘搜索自然流量少怎么办 4个月宝贝不食欲下降怎么办 淘宝商家预售时间到了不发货怎么办 淘宝修改类目被处置管控了怎么办 淘宝换手机号是已经注册了的怎么办 闲鱼违规把我淘宝店铺冻结了怎么办 开网店店主想买自己的东西怎么办 以前用微博登录头条的账号怎么办 公众号注册提示邮箱已被占用怎么办 学信网注册时出现邮箱被占用怎么办 手机淘宝店铺接不到买家消息怎么办 买了东西淘宝店铺没了怎么办 淘宝店铺直播间虚假交易违规怎么办 手机淘宝退款物流单号填错了怎么办 淘宝评价删除了卖家没有返现怎么办 想摆摊卖麻辣烫不知怎么摆怎么办 在淘宝卖东西买家退款不退货怎么办 在闲鱼网上买东西被骗了怎么办 开通花呗的手机号不用了怎么办 饿了么开业第一天没单量怎么办 淘宝新开店铺没有人来呀怎么办 刚开的淘宝店铺没有人买东西怎么办 开了一家龙虾店生意很淡怎么办? 新买的皮质小白鞋有点板脚怎么办 手机无效安装包与系统不兼容怎么办 发好的海参放进速冻后变小了怎么办 厨房地砖下面的下水管漏水怎么办? 埋在地下的暖气管漏水怎么办 安装个视频播放器视频全没了怎么办 奇迹mu圣导转职任务打不过怎么办 丈夫死后房产证过给妻子怎么办 学业与志愿活动冲突时你会怎么办 往宅正门前面有半园幕墙玻璃怎么办