Thursday, April 15, 2010

Learning OpenCV: Sequences

ประเภทข้อมูล sequence เป็นข้อมูลที่เก็บไว้ใน memory storage (จากตอนที่แล้ว) ตัวมันเองเป็น linked list ชนิดหนึ่งที่ชี้ไปยังโครงสร้างข้อมูลแบบอื่น ลองดูการประกาศ sequence


typedef struct CvSeq {
    int flags; // miscellaneous flags
    int header_size; // size of sequence header
    CvSeq* h_prev; // previous sequence
    CvSeq* h_next; // next sequence
    CvSeq* v_prev; // 2nd previous sequence
    CvSeq* v_next // 2nd next sequence
    int total; // total number of elements
    int elem_size; // size of sequence element in byte
    char* block_max; // maximal bound of the last block
    char* ptr; // current write pointer
    int delta_elems; // how many elements allocated
    // when the sequence grows
    CvMemStorage* storage; // where the sequence is stored
    CvSeqBlock* free_blocks; // free blocks list
    CvSeqBlock* first; // pointer to the first sequence block
}

จะเห็นมีข้อมูลที่สำคัญอยู่คือ total ที่บอกจำนวนในลิสต์ กับ pointer สำหรับ linked list สี่ตัวคือ h_prev, h_next, v_prev, v_next เป็น linked list ที่ชี้ได้สี่ทิศเลยทีเดียว

โดยตามปกติเช่นเดียว linked list ทั่วไป sequence จะสามารถจัดการข้อมูลที่อยู่บนหัวท้ายได้ดีกว่าข้อมูลที่อยู่ตรงกลาง 

โดยปกติ ฟังก์ชันใน OpenCV จะสร้าง sequence ให้เราโดยอัตโนมัติ เราแค่เรียกใช้ sequence ให้ถูกก็พอ ในกรณีที่ต้องการสร้างและลบ sequence เอง ใช้คำสั่งต่อไปนี้


CvSeq* cvCreateSeq(
    int seq_flags,
    int header_size,
    int elem_size,
    CvMemStorage* storage
);

แล้วลบด้วย


void cvClearSeq(
    CvSeq* seq
);



sequence ใช้หน่วยความจำใน memory storage (ที่ผ่าน parameter ใน cvCreateSeq) ในตอนที่ใช้คำสั่ง cvClearSeq หน่วยความจำจะไม่ถูก recycle (อ้างอิงจากตอนที่แล้ว เรื่อง memory storage)


คำสั่งจริงๆ ที่น่าจะใช้ของ sequence น่าจะเป็นการเข้าถึง object ใน sequence มากกว่า ลองดูคำสั่งตัวอย่างในหนังสือ


for( int i=0; itotal; ++i ) {
    CvPoint* p = (CvPoint*)cvGetSeqElem ( seq, i );
    printf(“(%d,%d)\n”, p->x, p->y );
}

จะเป้นการใช้คำสั่ง cvGetSeqElem โดยใส่ sequence เป็นพารามิเตอร์และ index i ที่ต้องการอย่าลืม casting ให้เป็นข้อมูลทีเราต้องการด้วย


คำสั่งอื่นๆ ในการจัดการ sequence จะขอลิสต์ไว้ ต่อไปนี้

คำสั่งในการ ค้นหา element ใน sequence

  • cvSeqElemIdx
คำสั่งในการเข้าถึง manipulate sequence

  • cvCloneSeq
  • cvSeqSlice
  • cvRemoveSlice
  • cvInsertSlice
การเรียง sequence การแบ่ง sequence และการค้นหาข้อมูลใน sequence

  • cvSeqSort
  • cvSeqSearch
  • cvSeqInvert
  • cvSeqPartition
ในฟังก์ชันส่วนนี้จะต้องกำหนดฟังก์ชันสำหรับเปรียบเทียบด้วย เพื่อที่ OpenCV จะได้เข้าใจว่า object สองตัวเรียงกันอย่างไร (เรียงตาม x หรือ y ใครที่เคยเขียน quick sort ใน C น่าจะนึกภาพออก) โดยกำหนดฟังก์ชันในรูปแบบนี้

typedef int (*CvCmpFunc)(const void* a, const void* b, void* userdata );

การใช้ sequence เป็น stack (สองหัวด้วยนะ)

  • cvSeqPush
  • cvSeqPop
  • cvSeqPushFront
  • cvSeqPopFront
  • cvSeqPushMulti
  • cvSeqPopMulti


การแทรก element กลาง sequence

  • cvSeqInsert
  • cvSeqRemove


การเปลี่ยนขนาด memory block size (จะได้ใช้เหรอ)

  • cvSetBlockSize
การแปลงระหว่าง array กับ sequence

  • cvCvtSeqToArray
  • cvMakeSeqHeaderForArray

ส่วนสุดท้ายคือการอ่านเขียน sequence ซึ่งมีประสิทธิภาพมากกว่าการ insert การ ใช้ฟังก์ชัน cvGetSeqElem โดยใช้วิธีสร้างตัว sequence reader กับ sequence writer ขึ้นมา การจัดการดูแล้วเหมือนการอ่านเขียนไฟล์ใน C

คำสั่งที่เกี่ยวข้องกับ sequence writer
  • cvStartWriteSeq
  • cvStartAppendToSeq
  • cvEndWriteSeq
  • cvFluseSeqWriter
  • CV_WRITE_SEQ_ELEM
  • CV_WRITE_SEQ_ELEM_VAR
คำสั่งที่เกี่ยวข้องกับ sequence reader
  • cvStartReadSeq
  • cvGetSeqReaderPos
  • cvSetSeqReaderPos
  • CV_NEXT_SEQ_ELEM
  • CV_PREV_SEQ_ELEM
  • CV_READ_SEQ_ELEM
  • CV_REV_READ_SEQ_ELEM
เนื่องจากการเขียนใน sequence writer น่าจะสำคัญจะอาจจะได้ใช้ เลยยกตัวอย่างในหนังสือมาเสียหน่อย





We will create a writer and append a
hundred random points drawn from a 320-by-240 rectangle to the new sequence.
CvSeqWriter writer;
cvStartWriteSeq( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage, &writer );
for( i = 0; i < 100; i++ )
{
    CvPoint pt; pt.x = rand()%320; pt.y = rand()%240;
    CV_WRITE_SEQ_ELEM( pt, writer );
}
CvSeq* seq = cvEndWriteSeq( &writer );


No comments:

Post a Comment