openCV中 cvSeq的用法說明

來源:互聯網
上載者:User
openCV中 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)

功能:初始化序列中的讀取過程

 

 

OpenCV CvSeq的內部結構探討

       一直困惑於CvSeq到底是個什麼樣的東西,因為曾經拿到別人寫的一個函數庫,其傳回值是一個CvSeq指標,我的工作是遍曆所有的Sequence,然
後刪除其中不符合要求的Sequence。由於沒有文檔,我當時並不知道我需要遍曆的是Sequence還是Sequence中的Element。於是我
寫下了類似如下的代碼:
CvSeq *pCurSeq = pInputSeq;<br />int index = 0;<br />while( pCurSeq=pCurSeq->h_next )<br />{<br /> if( process(pCurSeq) )<br /> {<br /> pCurSeq = pCurSeq->h_prev; //這裡為了簡單不考慮是否為列表頭<br /> cvSeqRemove(pInputSeq, index);<br /> --index;<br /> }<br /> ++index;<br />}


事實證明這段代碼是錯誤的,而且往往返回的錯誤資訊是
>
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) /<br /> int flags; /* micsellaneous flags */ /<br /> int header_size; /* size of sequence header */ /<br /> struct node_type* h_prev; /* previous sequence */ /<br /> struct node_type* h_next; /* next sequence */ /<br /> struct node_type* v_prev; /* 2nd previous sequence */ /<br /> struct node_type* v_next /* 2nd next sequence */<br />/*<br /> Read/Write sequence.<br /> Elements can be dynamically inserted to or deleted from the sequence.<br />*/<br />#define CV_SEQUENCE_FIELDS() /<br /> CV_TREE_NODE_FIELDS(CvSeq); /<br /> int total; /* total number of elements */ /<br /> int elem_size; /* size of sequence element in bytes */ /<br /> char* block_max; /* maximal bound of the last block */ /<br /> char* ptr; /* current write pointer */ /<br /> int delta_elems; /* how many elements allocated when the seq grows */ /<br /> CvMemStorage* storage; /* where the seq is stored */ /<br /> CvSeqBlock* free_blocks; /* free blocks list */ /<br /> CvSeqBlock* first; /* pointer to the first sequence block */<br />typedef struct CvSeq<br />{<br /> CV_SEQUENCE_FIELDS()<br />}<br />CvSeq;<br />


原來CvSeq本身就是一個可增長的序列,CvSeq::total是指序列內部有效元素的個數;而h_next和h_prev並不是指向CvSeq內部元
素的指標,它們是指向其它CvSeq的。再回到文章最初的代碼,我們可以看到該代碼具有邏輯上的錯誤,首先while語句遍曆的是所有的CvSeq,使用
process處理每一個CvSeq,而遇到需要刪除的CvSeq時,又使用才cvSeqRemove刪除當前CvSeq中的第index個元素。實際上
此時index很可能超出了當前CvSeq中總元素的個數,所以出現了超出邊界的錯誤。正確的做法是直接刪除該CvSeq。
CvSeq *pCurSeq = pInputSeq;<br />CvSeq *pOldSeq = NULL;<br />while( pCurSeq )<br />{<br /> if( process(pCurSeq) )<br /> {<br /> pOldSeq = pCurSeq;<br /> if(pOldSeq->h_prev)<br /> {<br /> pCurSeq = pOldSeq->h_prev;<br /> pCurSeq->h_next = pOldSeq->h_next;<br /> pOldSeq->h_next->h_prev = pCurSeq;<br /> pCurSeq=pCurSeq->h_next;<br /> cvClearSeq( pOldSeq );<br /> }<br /> else<br /> {<br /> pCurSeq = pOldSeq->h_next;<br /> pCurSeq->h_prev = NULL;<br /> cvClearSeq( pOldSeq );<br /> }<br /> }<br /> else<br /> {<br /> pCurSeq=pCurSeq->h_next;<br /> }<br />}

後來在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/

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.