OpenCV的序列数据结构(CvSeq)
序列是内存存储器中可以存储的一种对象.序列是某种结构的链表.OpenCV中,序列可以存储多种不同的结构.你可以将序列想象为许多编程语言中都存在的容器类或容器类模版(如C++中的vector).学列在内存被实现为一个双端队列(deque).因此序列可以实现快速的随机访问,已经快速删除顶端的元素,但是从中间删除元素则稍慢些.1.数据结构seq数据结构如下查看文本打印
原文来自: http://www.verydemo.com/demo_c128_i147992.html
序列是内存存储器中可以存储的一种对象.序列是某种结构的链表.OpenCV中,序列可以存储多种不同的结构.你可以将序列想象为许多编程语言中都存在的容器类或容器类模版(如C++中的vector).学列在内存被实现为一个双端队列(deque).因此序列可以实现快速的随机访问,已经快速删除顶端的元素,但是从中间删除元素则稍慢些.
1.数据结构
seq数据结构如下
- #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 /* 垂直方向上的下一个序列 */
- /*
- Read/Write sequence.
- Elements can be dynamically inserted to or deleted from the sequence.
- */
- #define CV_SEQUENCE_FIELDS() \
- CV_TREE_NODE_FIELDS(CvSeq); \
- int total; /* 元素总和 */ \
- int elem_size; /* 序列元素的大小,用字节表示. */ \
- schar* block_max; /* 最后块的最大区间 */ \
- schar* ptr; /* 写指针的当前位置 */ \
- int delta_elems; /* 当序列增长时有多少元素需要重新分配(序列的粒度). */ \
- CvMemStorage* storage; /* Where the seq is stored. */ \
- CvSeqBlock* free_blocks; /* 自由块列表 */ \
- CvSeqBlock* first; /* 指向第一个块的指针 */
- typedef struct CvSeq
- {
- CV_SEQUENCE_FIELDS()
- }
- 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 /* 垂直方向上的下一个序列 */
- /*
- Read/Write sequence.
- Elements can be dynamically inserted to or deleted from the sequence.
- */
- #define CV_SEQUENCE_FIELDS() \
- CV_TREE_NODE_FIELDS(CvSeq); \
- int total; /* 元素总和 */ \
- int elem_size; /* 序列元素的大小,用字节表示. */ \
- schar* block_max; /* 最后块的最大区间 */ \
- schar* ptr; /* 写指针的当前位置 */ \
- int delta_elems; /* 当序列增长时有多少元素需要重新分配(序列的粒度). */ \
- CvMemStorage* storage; /* Where the seq is stored. */ \
- CvSeqBlock* free_blocks; /* 自由块列表 */ \
- CvSeqBlock* first; /* 指向第一个块的指针 */
- typedef struct CvSeq
- {
- CV_SEQUENCE_FIELDS()
- }
- CvSeq;
结构 CvSeq是所有OpenCV动态 数据结构 的基础
通过不同寻常的宏定义,简化了带有附加参数的结构CvSeq的扩展.为了扩展CvSeq,用户可以定义一个新的数据结构,也可以在宏CV_SEQUENCE_FIELDS()所包括的CvSeq域后再放入用户自定义的域.
序列有两种类型:稠密序列和稀疏序列.稠密序列都派生于CvSeq,用来代表可扩展的一维数组----向量,栈,队列和双端队列等;数据间不存在空隙(即连续存放),如果从序列中删除元素或将新元素插入到序列中(不是两端),则次元素后边的相关元素会被移动.稀疏序列都派生于CvSet,是由节点组成的序列,每个节点或者被占用空间或者是空,由flags标识指定.这些序列作为无序的数据结构而被使用,如点集,图,和哈希表等.
域header_size含有序列头部节点的实际大小,此值大于或等于sizeof(CvSeq)
域h_prev,h_next,v_prev,v_next可用来创建不同序列的层次结构.域h_prev和h_next指向同意层次结构的前一个和后一个序列,域v_prev和v_next指向垂直方向结构上的前一个和后一个序列,即父亲和子孙
域first指向第一个序列块
域total包含稠密序列的总元素数和稀疏序列被分配的节点数
域flags的高16位描述(包含)特定的动态结构类型(CV_SEQ_MAGIC_VAL表示稠密序列,CV_SET_MAGIC_VAL表示稀疏序列),flags本身同事还包含形形色色的信息.
flags的最低CV_SEQ_ELTYPE_BITS位包含元素类型的ID(标识符).大多数处理函数并不会用到元素类型,而只会用到存放在elem_size中的元素大小.如果序列中包含CvMat结构的数据,则元素的类型就与CvMat中元素的类型相匹配,如CV_32SC2表示由二维空间中的点组成的序列,CV_32FC1表示由浮点数组成的序列等.
通过宏CV_SEG_ELTYPE(seq_header_ptr)来获取序列中元素的类型.处理数字序列的函数判断是elem_size等同于序列元素的大小.除了与CvMat兼容的类型外,还有以下几个在头文件中定义的额外类型.
(1)标准的序列元素类型
- #define CV_SEQ_ELTYPE_POINT CV_32SC2 /* (x,y) */
- #define CV_SEQ_ELTYPE_CODE CV_8UC1 /* freeman code: 0..7 */
- #define CV_SEQ_ELTYPE_GENERIC 0
- #define CV_SEQ_ELTYPE_PTR CV_USRTYPE1
- #define CV_SEQ_ELTYPE_PPOINT CV_SEQ_ELTYPE_PTR /* &(x,y) */
- #define CV_SEQ_ELTYPE_INDEX CV_32SC1 /* #(x,y) */
- #define CV_SEQ_ELTYPE_GRAPH_EDGE 0 /* &next_o, &next_d, &vtx_o, &vtx_d */
- #define CV_SEQ_ELTYPE_GRAPH_VERTEX 0 /* first_edge, &(x,y) */
- #define CV_SEQ_ELTYPE_TRIAN_ATR 0 /* vertex of the binary tree */
- #define CV_SEQ_ELTYPE_CONNECTED_COMP 0 /* connected component */
- #define CV_SEQ_ELTYPE_POINT3D CV_32FC3 /* (x,y,z) */
- #define CV_SEQ_ELTYPE_POINT CV_32SC2 /* (x,y) */
- #define CV_SEQ_ELTYPE_CODE CV_8UC1 /* freeman code: 0..7 */
- #define CV_SEQ_ELTYPE_GENERIC 0
- #define CV_SEQ_ELTYPE_PTR CV_USRTYPE1
- #define CV_SEQ_ELTYPE_PPOINT CV_SEQ_ELTYPE_PTR /* &(x,y) */
- #define CV_SEQ_ELTYPE_INDEX CV_32SC1 /* #(x,y) */
- #define CV_SEQ_ELTYPE_GRAPH_EDGE 0 /* &next_o, &next_d, &vtx_o, &vtx_d */
- #define CV_SEQ_ELTYPE_GRAPH_VERTEX 0 /* first_edge, &(x,y) */
- #define CV_SEQ_ELTYPE_TRIAN_ATR 0 /* vertex of the binary tree */
- #define CV_SEQ_ELTYPE_CONNECTED_COMP 0 /* connected component */
- #define CV_SEQ_ELTYPE_POINT3D CV_32FC3 /* (x,y,z) */
(2)通用 序列 类型
- #define CV_SEQ_KIND_GENERIC (0 << CV_SEQ_ELTYPE_BITS)
- #define CV_SEQ_KIND_GENERIC (0 << CV_SEQ_ELTYPE_BITS)
(3)稠密 数据 类型
- #define CV_SEQ_KIND_CURVE (1 << CV_SEQ_ELTYPE_BITS)
- #define CV_SEQ_KIND_BIN_TREE (2 << CV_SEQ_ELTYPE_BITS)
- #define CV_SEQ_KIND_CURVE (1 << CV_SEQ_ELTYPE_BITS)
- #define CV_SEQ_KIND_BIN_TREE (2 << CV_SEQ_ELTYPE_BITS)
(4)稀疏 数据 类型
- #define CV_SEQ_KIND_GRAPH (1 << CV_SEQ_ELTYPE_BITS)
- #define CV_SEQ_KIND_SUBDIV2D (2 << CV_SEQ_ELTYPE_BITS)
- #define CV_SEQ_KIND_GRAPH (1 << CV_SEQ_ELTYPE_BITS)
- #define CV_SEQ_KIND_SUBDIV2D (2 << CV_SEQ_ELTYPE_BITS)
CvSeqBlock 序列 块 结构 如下
- typedef struct CvSeqBlock
- {
- struct CvSeqBlock* prev; /* Previous sequence block. */
- struct CvSeqBlock* next; /* Next sequence block. */
- int start_index; /* Index of the first element in the block + */
- /* sequence->first->start_index. */
- int count; /* Number of elements in the block. */
- schar* data; /* Pointer to the first element of the block. */
- }
- CvSeqBlock;
- typedef struct CvSeqBlock
- {
- struct CvSeqBlock* prev; /* Previous sequence block. */
- struct CvSeqBlock* next; /* Next sequence block. */
- int start_index; /* Index of the first element in the block + */
- /* sequence->first->start_index. */
- int count; /* Number of elements in the block. */
- schar* data; /* Pointer to the first element of the block. */
- }
- CvSeqBlock;
序列 块构成一个双向循环列表,因此,指针prev和next永远不为NULL,而总是指向 序列 中的前一个和后一个 序列 块.也就是说,最后一个 序列 块的next指向 序列 中的第一个块,而第一个块的prev指向最后一个块.也就是说,最后一个 序列 块的next指向 序列 中块的位置.例如,一个含有10个元素的 序列 被分成3块,每块的大小分别为3,5和2,若第一块的参数start_index为2,则该 序列 的(start_index,count)对的值相应为(2,3),(5,5)和(10,2).第一个块的参数start_index通常为0,除非已有一些元素被插入 序列 中.
CvSlice对序列分割进行了定义,结构如下
- typedef struct CvSlice
- {
- int start_index, end_index;
- }
- CvSlice;
- CV_INLINE CvSlice cvSlice( int start, int end )
- {
- CvSlice slice;
- slice.start_index = start;
- slice.end_index = end;
- return slice;
- }
- #define CV_WHOLE_SEQ_END_INDEX 0x3fffffff
- #define CV_WHOLE_SEQ cvSlice(0, CV_WHOLE_SEQ_END_INDEX)
- typedef struct CvSlice
- {
- int start_index, end_index;
- }
- CvSlice;
- CV_INLINE CvSlice cvSlice( int start, int end )
- {
- CvSlice slice;
- slice.start_index = start;
- slice.end_index = end;
- return slice;
- }
- #define CV_WHOLE_SEQ_END_INDEX 0x3fffffff
- #define CV_WHOLE_SEQ cvSlice(0, CV_WHOLE_SEQ_END_INDEX)
下面语句用来计算 序列 分割长度
- int cvSliceLength(CvSlic slice,const CvSeq* seq);
- int cvSliceLength(CvSlic slice,const CvSeq* seq);
有关序列的一些操作都将结构CvSlice作为输入参数,默认情况下该参数通常被设置成整个序列(调用CV_WHOLE_SEQ实现).start_index和end_index中的任何一个都可以是负数,或者超过序列长度,start_index是闭界,end_index是开界.如果两者相等,则分割被认为是空分割(即不包含任何元素).由于序列被看作是循环结构,所以分割时可以选择序列中靠后的几个元素,分割后靠前的元素反而跟在它们的后面,如cvSlice(-2,3).函数使用下列方法来规范分割参数.首先,调用cvSliceLength决定分割长度,然后,使用类似于函数cvGetElem的参数index来规范start_index(例如允许使用负数).实际分分割操作起始于规范化了的start_index,中止于start_index + cvSliceLength()(再次假设序列是循环结构).
如果次函数不接受分割参数,但仍想要处理序列的某一部分,则可使用函数cvSeqSlice来获取子序列,
2.数据操作
(1)CreatSeq
功能:
函数cvCreatSeq创建一序列并返回指向该序列的指针.
格式
CvSeq* cvCreatSeq(int seq_flags,int header_size, int elem_size,CvMemStorage* storage);
参数:
seq_flags 序列的符号标志.如果序列不被传递给任何需使用特定序列的函数,则将他设为0,否则从预定义的序列类型中选择一合适类型.
header_size 序列头部的大小,必须大于或等于sizeof(CvSeq).如果指定了序列类型或序列扩展名,则次类型必须适合基类的头部大小.
elem_size 元素的大小,以字节为单位.此大小必须与序列类型一致.例如,对于一个店序列,应当指定元素类型为CV_SEQ_ELTYPE_POINT,参数elem_size必须等于sizeof(CvPoint)
storage 序列的位置.
说明
函数在存储块中分配序列的头部作为一个连续块,并将结构CvSeq的flags,elem_size,header_size和storage各域的值设置为从此函数传递过来的值,设置delta_elems为默认(可通过函数cvSetSeqBlockSize对其重新赋值),清空其他的头部域,包括前sizeof(CvSeq)字节空间.
(2)SetSeqBlockSize
功能:
函数cvSetSeqBlockSize设置序列块的大小
格式
void cvSetSeqBlockSize(CvSeq* seq,int delta_emems);
参数
seq 序列
delta_elems 满足元素所需块的大小
说明
函数cvSetSeqBlockSize将对内存分配的粒度产生影响,当序列缓冲区中的空间消耗完时,函数为delta_elems个序列元素分配空间.如果新分配的空间与之前分配的空间相邻,则两块合并;否则,创建一个新的序列块.因此,参数值delta_elems越大,序列中出现碎片的可能性就越小;不过内存中更多的空间被浪费.当序列被创建后,参数delta_elems的大小被设置为默认大小(1K).之后,可随时调用此函数,并影响内存的分配.次函数可修改传递过来的参数值,以满足内存块的大小限制.
(3)SeqPush
- 功能
- 函数cvSeqPush添加元素到序列的尾部
- 格式
- char* cvSeqPush(CvSeq* seq,void* element = NULL);
- 参数
- seq 块
- element 添加的元素
- 说明:
- 函数cvSeqPush在序列块的尾部添加一元素并返回指向该元素的指针.如果输入参数为NULL,则函数仅分配一空间,留给下一个元素使用.下列代码说明了如何使用该函数去分配一个空间.
- CvMemStorage* storage = cvCreateMemStorage(0);
- CvSeq* seq = cvCreateSeq(CV_32SC1,sizeof(CvSeq),sizeof(int),storage);
- int i;
- for (int i=0;i<100;i++)
- {
- int* added = (int*)cvSeqPush(seq,&i);
- printf("%d is added",*added);
- }
- cvReleaseMemStorage(&storage);
- 函数cvSeqPush的时间复杂度为O(1).如果需要分配并使用的空间较大,则可使用分配较快的函数(见cvStartWriterSeq和相关函数)
- 功能
- 函数cvSeqPush添加元素到序列的尾部
- 格式
- char* cvSeqPush(CvSeq* seq,void* element = NULL);
- 参数
- seq 块
- element 添加的元素
- 说明:
- 函数cvSeqPush在序列块的尾部添加一元素并返回指向该元素的指针.如果输入参数为NULL,则函数仅分配一空间,留给下一个元素使用.下列代码说明了如何使用该函数去分配一个空间.
- CvMemStorage* storage = cvCreateMemStorage(0);
- CvSeq* seq = cvCreateSeq(CV_32SC1,sizeof(CvSeq),sizeof(int),storage);
- int i;
- for (int i=0;i<100;i++)
- {
- int* added = (int*)cvSeqPush(seq,&i);
- printf("%d is added",*added);
- }
- cvReleaseMemStorage(&storage);
- 函数cvSeqPush的时间复杂度为O(1).如果需要分配并使用的空间较大,则可使用分配较快的函数(见cvStartWriterSeq和相关函数)
(4)SeqPop
功能:
函数cvSeqPop删除序列的尾部元素
格式
void cvSeqPop(CvSeq* seq,void* element =NULL);
参数:
seq 序列
element 可选参数.如果改指针不为空,则赋值被删除元素到指针所指位置.
说明:
函数cvSeqPop从序列中删除一元素.如果序列已经为空,则报告错误.函数的事件复杂度为O(1).
(5)SeqPushFront
功能
函数cvSeqPushFront在序列头部添加元素
格式
char* cvSeqPushfront(CvSeq* seq,void* element = NULL);
参数:
seq 序列
element 添加的元素.
说明
函数cvSeqPushFront类似于cvSeqPush,不过是在序列头部添加元素.其时间复杂度为O(1).
(6)SeqPopFront
功能:
函数cvSeqPopFront删除序列的头部元素
格式
void cvSeqPop(CvSeq* seq,void* element =NULL);
参数:
seq 序列
element 可选参数.如果改指针不为空,则赋值被删除元素到指针所指位置.
说明:
函数cvSeqPop从序列中删除一元素.如果序列已经为空,则报告错误.函数的事件复杂度为O(1).
(7)SeqPushMulti
功能
函数cvSeqPushMulti在序列头部或尾部添加多个元素
格式
void cvSeqPushMulti(CvSeq* seq,void* elements,int count , int in_font = 0);
参数
seq 序列
elements 待添加的元素
count 添加的元素个数
in_front 标识在头部haishi在尾部添加元素.为下列值之一:
CV_BACK(=0) 在序列的尾部添加元素
CV_FRONT(≠ 0) 在序列的头部添加元素
说明
带添加元素按输入数组中的顺序被添加到序列中,而且他们可以添加到不同的序列中.
(8)SeqPopMulti
功能
函数cvSeqPopMulti删除多个序列头部或尾部的元素.
格式
void cvSeqPopMulti(CvSeq* seq,void* elements,int count , int in_font = 0);
参数
seq 序列
elements 待删除的元素
count 待删除的元素个数
in_front 标识在头部haishi在尾部添加元素.为下列值之一:
CV_BACK(=0) 在序列的尾部添加元素
CV_FRONT(≠ 0) 在序列的头部添加元素
说明如果待删除元素的个数超过序列中的元素总数,则函数将删除所有元素.
(9)SeqInsert
- 功能
- 函数cvSeqInsert在序列中插入元素
- 格式
- char* cvSeqInsert(CvSeq* seq, int before_index, void* element = NULL);
- 参数
- seq 序列
- before_index 元素插入的位置(即索引).如果插入的位置在0(允许的参数最小值)之前,则该函数等同于函数cvSeqPushFront;如果是在seq_total(允许的参数最大值)之后,则函数等同于cvSeqPush
- element 待插入的元素
- 说明
- 函数cvSeqIndsert移动从被插入位置到序列尾部的所有元素,如果指针element不为NULL,则将element中的元素复制到指定的位置.函数返回指向被插入元素的指针.
- 功能
- 函数cvSeqInsert在序列中插入元素
- 格式
- char* cvSeqInsert(CvSeq* seq, int before_index, void* element = NULL);
- 参数
- seq 序列
- before_index 元素插入的位置(即索引).如果插入的位置在0(允许的参数最小值)之前,则该函数等同于函数cvSeqPushFront;如果是在seq_total(允许的参数最大值)之后,则函数等同于cvSeqPush
- element 待插入的元素
- 说明
- 函数cvSeqIndsert移动从被插入位置到序列尾部的所有元素,如果指针element不为NULL,则将element中的元素复制到指定的位置.函数返回指向被插入元素的指针.
(10)SeqRemove
功能
函数cvSeqRemove删除索引指定的元素
格式
void cvSeqRemove(CvSeq* seq,int index);
参数
seq 序列
index 被删除的元素索引
说明
如果索引超出了序列的范围,或函数企图从空序列中删除元素,则报告错误.函数通过移动序列中的元素来删除指定的元素
(11)ClearSeq
功能
函数cvClearSeq删除序列中的所有元素
格式
void cvClearSeq(CvSeq* seq);
参数
seq 序列
说明
函数不会将不在使用的内存返回到存储器中,当新元素添加到序列中时,可重新使用该内存.函数的时间复杂度为O(1).
(12)GetSeqElem
功能
函数cvGetSeqElem返回索引指定的元素指针
格式
char* cvGetSeqElem(const CvSeq* seq,int index);
#define CV_GET_SEQ_ELEM(TYPE,seq,index)\
(TYPE* )cvGetSeqElem((CvSeq*)(Seq),(index))
参数
seq 序列
index 索引
说明
函数cvGetSeqElem查找序列中由索引指定的元素,并返回指向该元素的指针.如果元素不存在则返回0.函数索引支持负数,即-1代表序列的最后一个元素,-2代表倒数第二个元素,等等.如果序列只包含一个块,或者所需元素在第一个块中,那么应当使用宏CV_GET_SEQ_ELEM(elemType,seq,index),宏中参数elemType是序列中元素的类型(如CvPoint),参数seq表示序列,参数index代表所需元素的索引.该宏首先核查所需元素是否属于第一个块,若是则返回该元素;否则,该宏调用主函数cvGetSeqElem.如果索引为负数,则总调用函数cvGetSeqElem.函数的时间复杂度为O(1),并假设块的大小比元素的数量小.
(13)SeqElemIdx
功能
函数cvSeqElemIdx返回序列中元素的索引
格式
int cvSeqElemIdx(const CvSeq* seq,const void* element, CvSeqBlock** blodk=NULL);
参数
seq序列
element 指向序列中元素的指针
block 可选参数,如果不为空,则存放包含所指元素的块的地址
说明
函数cvSeqElemIdx放回元素的索引,如果该元素不在此序列中,则返回一个负数
(14)CvtSeqToArray
功能
函数cvCvtSeqToArray复制序列中的元素到一个连续的内存块中
格式
void* cvCvtSeqToArray(const CvSeq* seq, void* elements, CvSlice slice= CV_WHILE_SEQ);
参数
seq 序列
elements 指向目的的数组(存放已复制的元素)的指针,指针指向的空间必须足够大.
slice 复制序列部分到数组中.
说明
函数cvCvtSeqToArray复制整个或部分序列到指定的缓冲区中,并返回指向该缓冲区的指针.
下列说明如何将序列中的点集提取出来
- CvMemStorage* stor;
- CvSeq* cont;
- CvPoint* PointArray;
- CvPoint2D32f* PointArray2D32f;
- float temp;
- //创建动态结构和序列
- stor = cvCreateMemStorage(0);
- cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT,sizeof(CvSeq),sizeof(CvPoint),stor);
- //寻找所有轮廓并放置在序列中
- cvFindContours(src,stor,&cont,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_NONE,cvPoint(0,0));
- for (;cont;cont=cont->h_next)
- {
- int i;
- int count = cont->total;
- CvPoint center;
- CvSize size;
- PointArray = (CvPoint*) malloc(count* sizeof(CvPoint));
- PointArray2D32f = (CvPoint2D32f*)malloc(count* sizeof(CvPoint2D32f));
- //获取点内容
- cvCvtSeqToArray(cont,PointArray,CV_WHOLE_SEQ);
- //把点放置到集合中
- for (i=0;i<count ;i++)
- {
- PointArray2D32f[i].x =(float)PointArray[i].x;
- PointArray2D32f[i].y = (float)PointArray[i].y;
- }
- //释放内存
- free(PointArray);
- free(PointArray2D32f);
- //free(box);
- }
- CvMemStorage* stor;
- CvSeq* cont;
- CvPoint* PointArray;
- CvPoint2D32f* PointArray2D32f;
- float temp;
- //创建动态结构和序列
- stor = cvCreateMemStorage(0);
- cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT,sizeof(CvSeq),sizeof(CvPoint),stor);
- //寻找所有轮廓并放置在序列中
- cvFindContours(src,stor,&cont,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_NONE,cvPoint(0,0));
- for (;cont;cont=cont->h_next)
- {
- int i;
- int count = cont->total;
- CvPoint center;
- CvSize size;
- PointArray = (CvPoint*) malloc(count* sizeof(CvPoint));
- PointArray2D32f = (CvPoint2D32f*)malloc(count* sizeof(CvPoint2D32f));
- //获取点内容
- cvCvtSeqToArray(cont,PointArray,CV_WHOLE_SEQ);
- //把点放置到集合中
- for (i=0;i<count ;i++)
- {
- PointArray2D32f[i].x =(float)PointArray[i].x;
- PointArray2D32f[i].y = (float)PointArray[i].y;
- }
- //释放内存
- free(PointArray);
- free(PointArray2D32f);
- //free(box);
- }
(15)MakeSeqHead而ForArray
功能
函数cvMakeSeqHeaderForArray构建序列
格式
cvMakeSeqHeaderForArray( int seq_type, int header_size,
int elem_size, void* elements, int total,
CvSeq* seq, CvSeqBlock* block );
参数
seq_type 序列的类型
header_size 序列的头部大小.该值必须大于等于数组的大小
elem_size 元素的大小
elements 星辰该序列的元素
total 序列中元素的总数.此值必须等于elements中元素的个数
seq 指向被用做序列头部分局部变量
block 指向局部变量的指针
说明
函数cvMakeSeqHeaderForArray初始化序列的头部.序列头和序列块由用户分配.该函数不复制数据.创建的序列只包含一个块及一个NULL指针,因此用户可以读取指针.但若试图将元素添加到序列中,则多数会引发错误.
(16)SeqSlice
功能
函数cvSeqSlice为序列碎皮建立独立的头
格式
CvSeq* cvSeqSlice(const CvSeq* seq,CvSlice slice, CvMemStorage* storage = NULL, int copy_data = 0);
参数
seq 序列
slice 部分序列块
storage 存放新序列和复制数据(如果需要)的目的的存储空间.如果为NULL,则此函数使用存储输入序列的存储空间
copy_data 标志是否要复制元素,如果不为0,则需要复制;否则,则不需要复制
说明
函数cvSeqSlice创建一序列,该序列为输入序列中特定的一部分(slice).新序列或者与原序列共享元素或者拥有自己的一个备份.因此,如果需要处理某部分序列,而函数却没有slice参数,则可使用次函数获取该序列
(17)cloneSeq
功能
函数cvCloneSeq创建序列的一个备份
格式
CvSeq* cvCloneSeq(const CvSeq* seq,CvMemStorage* storage= NULL);
参数
seq 序列
storage 存放新序列头部分和复制数据(如果需要)的目的存储空间.如果为NULL,则此函数使用存储输入序列的存储空间
说明
函数cvCloneSeq创建输入序列的一个完全备份.调用函数cvCloneSeq(seq,storage)等同于调用函数cvSeqSlice(seq,CV_WHolE_SEQ,storage,1);
(18)SeqRemoveSlice
功能
函数cvSeqRemoveSlice删除序列中的slice部分
格式
void cvSeqRemoveSlice(CvSeq* seq,CvSlice slice);
参数
seq 序列
slice 序列中被删除的部分
(19)SeqInsertSlice
功能
函数cvSeqInsertSlice在序列中插入一个数组
格式
void cvSeqInsertSlice(CvSeq* seq,int before_index,const CvArr* from_arr);
seq 序列
before_index 插入位置
from_arr 获取元素的数组
说明
函数cvSeqInsertSlice在指定位置插入来自数组from_arr中的所有元素.数组from_arr可以是一个矩阵,也可以是另外一个序列
(20)SeqInvert
功能
函数cvSeqInvert对序列中的元素进行逆序操作.
格式
void cvSeqInvert(CvSeq* seq);
参数
seq 序列
说明
函数cvSeqInvert对序列进行逆序操作,也就是说,使第一个元素成为最后一个,最后一个元素成为第一个
(21)SeqSort
- 功能
- 函数cvSeqSort使用特定的比较函数对序列中的元素进行排序
- 在使用特定的比较函数应先进行如下声明
- /*要实现的比较运算是: a<b?-1;a>b?1:0*/
- typedef int (CV_CDECL* CvCmpFunc)(const void* a, const void*b,void* userdata);
- 格式
- void cvSeqSort(CvSeq* seq,CvCmpFunc,void* userdata = NULL);
- 参数
- seq 待排序的序列
- func 比较函数,按照元素间的大小关系返回负数,零,或者正数
- userdata 传递给比较函数的用户参数,在某些情况下,可避免全局变量的使用
- 说明
- 函数cvSeqSort使用特定的标准对序列进行排序.下面是一个函数实例
- </b?-1;a>
- 功能
- 函数cvSeqSort使用特定的比较函数对序列中的元素进行排序
- 在使用特定的比较函数应先进行如下声明
- /*要实现的比较运算是: ab?1:0*/
- typedef int (CV_CDECL* CvCmpFunc)(const void* a, const void*b,void* userdata);
- 格式
- void cvSeqSort(CvSeq* seq,CvCmpFunc,void* userdata = NULL);
- 参数
- seq 待排序的序列
- func 比较函数,按照元素间的大小关系返回负数,零,或者正数
- userdata 传递给比较函数的用户参数,在某些情况下,可避免全局变量的使用
- 说明
- 函数cvSeqSort使用特定的标准对序列进行排序.下面是一个函数实例
- 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 y_diff ? y_diff : x_diff;
- }
- CvMemStorage* storage = cvCreateMemStorage(0);
- CvSeq* seq = cvCreateSeq(CV_32SC2,sizeof(CvSeq),sizeof(CvPoint),storage);
- int i;
- for (int i=0;i<10;i++)
- {
- CvPoint pt;
- pt.x = rand() % 1000;
- pt.y = rand() % 1000;
- cvSeqPush(seq,&pt);
- }
- cvSeqSort(seq,cmp_func,0);
- //输出结果
- for (i=0;i < seq->total;i++)
- {
- CvPoint* pt = (CvPoint*) cvGetSeqElem(seq,i);
- printf("(%d,%d)",pt->x,pt->y);
- }
- cvReleaseMemStorage(&storage);
- 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 y_diff ? y_diff : x_diff;
- }
- CvMemStorage* storage = cvCreateMemStorage(0);
- CvSeq* seq = cvCreateSeq(CV_32SC2,sizeof(CvSeq),sizeof(CvPoint),storage);
- int i;
- for (int i=0;i<10;i++)
- {
- CvPoint pt;
- pt.x = rand() % 1000;
- pt.y = rand() % 1000;
- cvSeqPush(seq,&pt);
- }
- cvSeqSort(seq,cmp_func,0);
- //输出结果
- for (i=0;i < seq->total;i++)
- {
- CvPoint* pt = (CvPoint*) cvGetSeqElem(seq,i);
- printf("(%d,%d)",pt->x,pt->y);
- }
- cvReleaseMemStorage(&storage);
(22)SeqSearch
- 功能
- 函数cvSeqSearch查询序列中的元素
- 在使用比较函数之前应先进行如下声明
- /*要实现的比较运算是: a < b ? -1 :a > b ?1 : 0*/
- typedef int (Cv_CDECL * CvCmpFunc)(Const void* a,const void * b, void * userdata);
- 格式
- char* cvSeqSearch(CvSeq* seq,const void* elem, CvCmpFunc func , int is_sorted , int * elem_idx, void * userdata = NULL);
- 参数
- seq 序列
- elem 待查询的元素
- func 比较函数,按照元素间的大小关系放回负数,零或正数(见函数cvSeqSort中的解释)
- is_sorted 标志序列是否已经排序
- elem_idx 输出参数,已查找到的元素索引值
- Userdata 传递到比较函数的用户参数,在某些情况下,有助于避免使用全局变量.
- 说明
- 函数cvSeqSearch查找序列中的元素.如果序列已被排序,则使用二分查找(事件复杂度为O[log(N)]);否则使用简单线性查找.若查找元素不存在,则函数返回NULL指针,而将索引值设置为序列中的元素数(当使用线性查找时)或者是能够满足表达式seq(i) > elem的最小i值
- 功能
- 函数cvSeqSearch查询序列中的元素
- 在使用比较函数之前应先进行如下声明
- /*要实现的比较运算是: a < b ? -1 :a > b ?1 : 0*/
- typedef int (Cv_CDECL * CvCmpFunc)(Const void* a,const void * b, void * userdata);
- 格式
- char* cvSeqSearch(CvSeq* seq,const void* elem, CvCmpFunc func , int is_sorted , int * elem_idx, void * userdata = NULL);
- 参数
- seq 序列
- elem 待查询的元素
- func 比较函数,按照元素间的大小关系放回负数,零或正数(见函数cvSeqSort中的解释)
- is_sorted 标志序列是否已经排序
- elem_idx 输出参数,已查找到的元素索引值
- Userdata 传递到比较函数的用户参数,在某些情况下,有助于避免使用全局变量.
- 说明
- 函数cvSeqSearch查找序列中的元素.如果序列已被排序,则使用二分查找(事件复杂度为O[log(N)]);否则使用简单线性查找.若查找元素不存在,则函数返回NULL指针,而将索引值设置为序列中的元素数(当使用线性查找时)或者是能够满足表达式seq(i) > elem的最小i值
(23)StartAppendToSeq
功能
函数cvStartAppendToSeq将数据写如序列中,并初始化该过程
格式
void cvStartAppendToSeq(CvSeq* seq,CvSeqWriter* writer);
参数
seq 指向序列的指针
writer 写入部分的状态,由此函数初始化
说明
函数cvStartAppendToSeq对数据写入序列的过程初始化.通过宏CV_WRITE_SEQ_ELEM(wtitten_elem,writer)可以将要写入的元素添加到序列的尾部.
注意 在写入期间,对序列的其他操作可能会产生错误的结果,甚至破坏该序列(具体说明参见函数cvFlishSeqWriter的相关描述,有助于避免这些错误).
(24)StartWriterSeq
功能
函数cvStartWriteSeq创建新序列,并初始化写入状态
格式
void cvStartWriteSeq(int seq_flags, int header_size, int elem_size,CvMemStorage* storage, CvSeqWriter* writer);
参数
seq_flags 标志被创建的序列.如果序列还未传递给任何可处理特定序列类型的函数,则序列值等于0;否则,必须从之前定义的序列类型中选择一个合适的类型.
header_size 头部的大小.此参数值不小于sizeof(CvSeq).如果定义了某一类型或其扩展,则次参数必须与所定义类型的头大小相同
elem_size 元素的大小(以字节计),必须与序列类型一致.例如,如果创建了包含指针的序列(元素类型为CV_SEQ_ELTYPE_POINT),那么elem_size必须等于sizeof(CvPoint).
storage 序列(在内存的位置)
writer 写入部分的状态,由此函数初始化
说明
函数cvStartWriteSeq是函数cvCreateSeq与函数cvStartAppendToSeq的组合.指向被创建的序列指针存放在writer->seq中,该指针通过函数cvEndWriterSeq放回(应当在最后调用).
(25)EndWriteSeq
功能
函数cvEndWriteSeq
格式
CvSeq* cvEndWriteSeq(CvSeqWriter* writer);
参数
writer 写入部分的状态
说明
函数cvEndWriteSeq完成写入操作并返回指向被写入元素的序列的地址,同事,函数将截取最后那个不完整的序列块.块的剩余部分返回到内存之后,序列即可以被安全地读和写.
(26)FlushSeqWriter
功能
函数cvFlushSeqWriter根据写入状态刷新序列头部
格式
void cvFlushSeqWriter(CvSeqWriter* writer);
参数
writer 写入部分的状态
说明
函数cvFlishSeqWriter用来在写入过程中使用户在需要时读取序列中的元素,例如核查指定的条件.函数更新序列的头部,从而使读取序列中的数据成为可能.不过,写如操作并没有被关闭,因此随时都可以将数据写入序列.在某些需要经常刷新的算法中,应考虑使用cvSeqOush来代替此函数.
(27)StartReadSeq
功能
函数cvStartReadSeq初始化序列中的读取过程
格式
void cvStartReadSeq(const CvSeq* seq ,CvSeqRead* redaer,int reverse=0);
参数
seq 序列
reader 读取部分的状态,有此函数初始化
reverse 决定遍历序列的方向.如果为0,则读取顺序为从序列头部的元素开始;否则,从序列尾部开始.
说明
函数cvStartReadSeq初始化读取部分的状态.顺序读取可通过调用宏CV_READ_SEQ_ELEM(read_elem,reader)实现.逆序读取可通过调用宏CV_REV_READ_SEQ_ELEM(read_elem,reader)实现.这两个宏都将序列元素读入read_elem中,并将指针移到下一个元素.下列代码显示如果使用reader和writer
- CvMemStorage* storage = cvCreateMemStorage(0);
- CvSeq* seq = cvCreateSeq(CV_32SC1,sizeof(CvSeq),sizeof(int),storage);
- CvSeqWriter writer;
- CvSeqReader reader;
- int i;
- cvStartAppendToSeq(seq,&writer);
- for (i=0;i<10;i++)
- {
- int val = rand() % 100;
- CV_WRITE_SEQ_ELEM(val,writer);
- printf("%d is written\n",val);
- }
- cvEndWriteSeq(&writer);
- cvStartReadSeq(seq,&reader,0);
- for (i=0;i<seq->total;i++)
- {
- int val;
- #if 1
- CV_READ_SEQ_ELEM(val,reader);
- printf("%d is read\n",val);
- #else
- printf("%d is read\n",*(int*)reader.ptr);
- CV_NEXT_SEQ_ELEM(seq->elem_size,reader);
- #endif
- }
- cvReleaseMemStorage(&storage);
- CvMemStorage* storage = cvCreateMemStorage(0);
- CvSeq* seq = cvCreateSeq(CV_32SC1,sizeof(CvSeq),sizeof(int),storage);
- CvSeqWriter writer;
- CvSeqReader reader;
- int i;
- cvStartAppendToSeq(seq,&writer);
- for (i=0;i<10;i++)
- {
- int val = rand() % 100;
- CV_WRITE_SEQ_ELEM(val,writer);
- printf("%d is written\n",val);
- }
- cvEndWriteSeq(&writer);
- cvStartReadSeq(seq,&reader,0);
- for (i=0;i<seq->total;i++)
- {
- int val;
- #if 1
- CV_READ_SEQ_ELEM(val,reader);
- printf("%d is read\n",val);
- #else
- printf("%d is read\n",*(int*)reader.ptr);
- CV_NEXT_SEQ_ELEM(seq->elem_size,reader);
- #endif
- }
- cvReleaseMemStorage(&storage);
(28)GetSeqReaderPos
功能
函数cvGetSeqReaderPos返回当前读取器的位置
格式
int cvGetSeqReaderPos(CvSeqReader* reader);
参数
reader 读取器的状态
说明
函数cvGetSeqReaderPos放回当前reader的位置在(0到reader->seq->total-1之间)
(29)SetSeqReaderPos
- 功能
- 函数cvSetSeqReaderPos移动读取器到指定的位置
- 格式
- void cvSetSeqReaderPos(CvSeqReader* reader,int index, int is_relative = 0);
- 参数
- reader 读取器的状态
- index 索引的位置.如果使用绝对位置,则实际位置为index % reader->seq->total.
- is_relative 如果不为0,则索引(index)值为相对位置
- 说明
- 函数cvSetSeqReaderPos将读取器的位置移动到绝对位置,或相对于当前位置的相对位置上.
- 功能
- 函数cvSetSeqReaderPos移动读取器到指定的位置
- 格式
- void cvSetSeqReaderPos(CvSeqReader* reader,int index, int is_relative = 0);
- 参数
- reader 读取器的状态
- index 索引的位置.如果使用绝对位置,则实际位置为index % reader->seq->total.
- is_relative 如果不为0,则索引(index)值为相对位置
- 说明
- 函数cvSetSeqReaderPos将读取器的位置移动到绝对位置,或相对于当前位置的相对位置上.
更多推荐
所有评论(0)