차근차근/OpenCV

시퀀스(Sequence)

예쁜꽃이피었으면 2014. 8. 5. 16:58

http://lueseypid.tistory.com/archive/20130113?page=2



■ 시퀀스

시퀀스(Sequence)는 메모리 스토리지 내에 저장되는 객체들 중 하나이다. 스퀀스는 다른구조체들의 연결 리스트로, OpenCV는 다양한 객체로 구성된 시퀀스를 생성 할 수 있게한다. (다른 언어에존재하는 제너릭 컨테이너 클래스 혹은 컨테이너 클래스 템플릿과 같음)


 typedef struct CvSeq {

    int         flags;          /* 다양한 용도의 플래그 */

    int         header_size;    /* 스퀀스 헤더의 크기 */

    CvSeq*      h_prev;         /* 이전 시퀀스 */

    CvSeq*      h_next;         /* 다음 스퀀스 */

    CvSeq*      v_prev;         /* 2번전에 있는 시퀀스 */

    CvSeq*      v_next;         /* 2번후에 있는 스퀀스 */

 

    int         total;          /* 전체 원소의 개수 */

    int         elem_size;      /* 시퀀스 원소의 크기(바이트) */

    schar*      block_max;      /* 마지막 블록의 최대 크기 */ 

    schar*      ptr;            /* 현재 저장포인터 */ 

    int         delta_elems;    /* 시퀀스가 증가할때 얼마나 많은 원소들이 할당되는지를 나타냄 */

 

    CvMemStorage*      storage;       /* 시퀀스가 저장되어 있는 메모리 스토리지 */ 

    CvSeqBlock*        free_blocks;   /* 비어있는 블럭의 목록 */

    CvSeqBlock*        first;         /* 첫번째 시퀀스 블록을 가리키는 포인터 */

CvSeq;


■ 시퀀스 생성하기 - cvCreateSeq()

 CvSeq* cvCreateSeq(

        int seq_flags,                //시퀀스의 종류

        size_t header_size,           //시퀀스 헤더의 크기

        size_t elem_size,             //시퀀스가 포함할 객체의 크기

        CvMemStorage* storage  //시퀀스가 메모리를 할당할 메모리 스토리지

);


seq_flags에 사용되는 플래그들은 세가지 종류(시퀀스 객체타입, 시퀀스 종류타입, 스퀀스 특징 플래그)로 나눌수 있으며, OR비트 연산자를 통해 결합되어 사용할 수 있다. 하지만 플래그는 거의 사용되지 않는다. 사용자 정의 타입으로 구성된 시퀀스를 사용하기 위해서는 seq_flags에 단순히 0을 입력하고, 정확한 elem_size를 지정한다.


[seq_flag에 사용되는 플래그 보기]


■ 시퀀스 삭제하기

 void cvClearSeq(CvSeq* seq);



■ 시퀀스 원소에 접근

 schar* cvGetSeqElem(const CvSeq* seq, int index);

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

cvGetSeqElem()함수를 사용하여 임의로 선택된 원소에 접근한다.함수에 의해 반환된 값은 해당 데이터 타입으로 형변환하여 사용해야 한다. 

특정원소가 시퀀스 내부의 어느곳에 위치해 있는지 알아 내기 위해서는 cvSeqElemidx()함수를 사용한다. 하지만 이함수는 연산속도가 느리기때문에 자주 사용하는것은 효율적이지 않다.


■ 원소 삽입과 삭제

 void cvSeqInsertSlice(CvSeq* seq, int before_index, const CvArr* from_arr);

 void cvSeqRemoveSlice(CvSeq* seq, CvSlice slice);

이 두 함수의 평균 처리 시간의 시퀀스 전체 길이에 비례한다.


■ 시퀀스 블록 크기

 void cvSetSeqBlockSize(CvSeq* seq, int delta_elems);

시퀀스가 새로운 원소들을 저장할 메모리 공간이 추가로 필요할 때, 새로 할당될 메모리 전체 블록의 크기를 나타낸다. 


■ 시퀀스 리더, 라이터

시퀀스를 이용한 작업에서 최상의 성능을 얻기 위해서 시퀀스에 값을 저장하기 위한 CvSeqWriter 구조체와 시퀀스의 값을 읽어오기 위한 CvSeqReader 구조체를 사용한다.


CvSeqWriter 구조체

cvStartWriteSeq()함수를 이용하여 CvSeqWriter구조체를 초기화하고, 작업이 끝난후에는 cvEndWriteSeq()함수를 이용하여 사용을 종료한다.

 void cvStartWriteSeq(

        int seq_flags,

        int header_size,

        int elem_size,

        CvMemStorage* storage,

        CvSeqWriter* writer

 );

 CvSeq* cvEndWriteSeq(CvSeqWriter* writer);

 void cvStartAppendToSeq(CvSeq* seq, CvSeqWriter* writer);

 void cvFlushSeqWriter(CvSeqWriter* writer);


 CV_WRITE_SEQ_ELEM(elem, writer)

 CV_WRITE_SEQ_ELEM_VAR(elem_ptr, writer)

cvStartWriteSeq() : CvSeqWriter 구조체 초기화

cvEndWriteSeq() : CvSeqWriter 사용 종료

cvStartAppendToSeq() : 시퀀스 라이터가 시퀀스의 끝에 새로운 원소를 추가 할수 있도록 라이터를 초기화한다.

cvFlushSeqWriter() : CV_WRITE_SEQ_ELEM() 매크로 함수를 이용하여 시퀀스에 새로운 원소를 추가할때 cvEndWriteSeq()함수를 호출한 후 시퀀스의 내용이 완전히 갱신된다. cvFlushSeqWriter는 CvSeqWriter구조체를 종료하지 않고 시퀀스를 최신상태로 만든다.

CV_WRITE_SEQ_ELEM() : 시퀀스에 새로운 원소를 추가

CV_WRITE_SEQ_ELEM_VAR() : 시퀀스에 새로운 원소(포인터값)을 추가


CvSeqReader 구조체

 void cvStartReadSeq(

        const CvSeq* seq,

        CvSeqReader* reader,

        int reverse=0                 //reverse 값이 1이면 시퀀스를 역순으로 읽는다.

 );

 int cvGetSeqReaderPos(CvSeqReader* reader);

 void cvSetSeqReaderPos(

        CvSeqReader* reader,

        int index,

        int is_relative=0             //is_relative인자 값이 0 아니면 index 현재 리더 위치에 대한

 );                                   //상대적 오프셋값으로 계산한다.

 

 CV_NEXT_SEQ_ELEM(elem_size, reader)

 CV_PREV_SEQ_ELEM(elem_size, reader)

 CV_READ_SEQ_ELEM(elem, reader)

 CV_REV_READ_SEQ_ELEM(elem, reader)

cvStartReadSeq() : CvSeqReader 구조체를 초기화

cvGetSeqReaderPos() : 시퀀스 내에서 시퀀스 리더의 현재 위치를 가리키는 정수를 반환

cvSetSeqReaderPos() : 시퀀스 리더가 시퀀스 내 임의의 위치로 이동할 수 있도록 한다.

CV_NEXT_SEQ_ELEM(), CV_PREV_SEQ_ELEM() : 시퀀스의 앞 뒤로 이동

CV_READ_SEQ_ELEM(), CV_REV_READ_SEQ_ELEM() : 시퀀스에 저장된 값을 읽음



 #include <stdio.h>

#include <cv.h>

 

typedef struct MyPoint {

        int x;

        int y;

MyPoint;

 

int main() {

 

        CvMemStorage* memeStorage=cvCreateMemStorage(0);

        CvSeq* seq1=cvCreateSeq(0, sizeof(CvSeq),

               sizeof(MyPoint), memeStorage);

 

        MyPoint pt1={3, 3};

 

        //Sequence 데이터 삽입

        cvSeqInsert(seq1, 0, &pt1);

       

        //Sequence 넣은 데이터를 불러옴

        MyPoint* rtnPt1=(MyPoint*)cvGetSeqElem(seq1, 0);

 

        //출력

        printf("{%d, %d}\n", rtnPt1->x, rtnPt1->y);

 

 

        /************************************************************************/

        /* 시퀀스 리더라이터                                                 */

        /************************************************************************/

        printf("시퀀스 라이터를 이용한 Sequence생성\n");

       

        //시퀀스 리더 생성

        CvSeqWriter writer;

        cvStartWriteSeq(0, sizeof(CvSeq), sizeof(MyPoint), memeStorage, &writer);

 

        for(int i=0; i<100; i++) {

               MyPoint pt2;

               pt2.x=rand()%320;

               pt2.y=rand()%240;

               CV_WRITE_SEQ_ELEM(pt2, writer);

        }

 

        //시퀀스 라이터 종료

        CvSeq* seq2=cvEndWriteSeq(&writer);

 

        //시퀀스 리더 생성

        CvSeqReader reader;

        cvStartReadSeq(seq2, &reader, 0);

 

 

        for(int i=0; i<seq2->total; i++) {

               //Sequence 넣은 데이터를 불러옴

               MyPoint rtnPt2;

 

               cvSetSeqReaderPos(&reader, i);

               CV_READ_SEQ_ELEM(rtnPt2, reader);

 

               //출력

               printf("{%d, %d}\n", rtnPt2.x, rtnPt2.y);

        }

       

        cvReleaseMemStorage(&memeStorage);

 

}



반응형