OpenCV學習筆記之CXCORE篇

爲使得OpenCV的整個庫便於管理和擴充,將整個庫分紅若干子庫,CxCore是最重要的一個子庫,從「core"名字能夠看出,該庫提供了全部OpenCV運行時的一些最基本的數據結構,包括矩陣,數組的基本運算,包括出錯處理的一些基本函數。具體分爲下面若干部分。php

   

基礎結構: node

CvPoint

二維座標系下的點,類型爲整型算法

typedef struct CvPoint
 {
  int x; /* X座標, 一般以0爲基點 */
  int y; /* y座標, 一般以0爲基點 */
 }
CvPoint;
/* 構造函數 */
inline CvPoint cvPoint( int x, int y );
/* 從 CvPoint2D32f類型轉換得來 */
inline CvPoint cvPointFrom32f( CvPoint2D32f point )  

CvPoint2D32f

二維座標下的點,類型爲浮點canvas

typedef struct CvPoint2D32f
 {
  float x; /* X座標, 一般以0爲基點*/
  float y; /* Y座標, 一般以0爲基點*/
 }
CvPoint2D32f;
/* 構造函數 */
inline CvPoint2D32f cvPoint2D32f( double x, double y );
/* 從CvPoint轉換來 */
inline CvPoint2D32f cvPointTo32f( CvPoint point );

CvPoint3D32f

三維座標下的點,類型爲浮點數組

typedef struct CvPoint3D32f
 {
  float x; /* x-座標, 一般基於0 */
  float y; /* y-座標, 一般基於0 */
  float z; /* z-座標, 一般基於0 */
 }
 CvPoint3D32f;
/* 構造函數 */
inline CvPoint3D32f cvPoint3D32f( double x, double y, double z );

CvSize

矩形框大小,以像素爲精度緩存

typedef struct CvSize
 {
  int width;  /* 矩形寬 */
  int height; /* 矩形高 */
 }
 CvSize;
/* 構造函數 */
inline CvSize cvSize( int width, int height );

注意:構造函數的cv是小寫!安全

CvSize2D32f

以亞像素精度標量矩形框大小數據結構

typedef struct CvSize2D32f
 {
   float width;  /* 矩形寬 */
   float height; /* 矩形高 */
 }
 CvSize2D32f;
/* 構造函數*/
inline CvSize2D32f cvSize2D32f( double width, double height );
{
    CvSize2D32f s;

    s.width = (float)width;
    s.height = (float)height;

    return s;
}

CvRect

矩形框的偏移和大小閉包

typedef struct CvRect
 {
  int x; /* 方形的最左角的x-座標  */
  int y; /* 方形的最上或者最下角的y-座標 */
  int width; /* 寬 */
  int height; /* 高 */
 }
 CvRect;
/* 構造函數*/
inline CvRect cvRect( int x, int y, int width, int height );
   { CvRect os;
      
      os.x = x;
      os.y = y;
      os.width = width;
      os.height = heigth;
      
      reture os;}

 

CvScalarapp

可存放在1-,2-,3-,4-TUPLE類型的捆綁數據的容器

typedef struct CvScalar
 {
  double val[4]
 }
 CvScalar;
/* 構造函數:用val0初始化val[0]用val1初始化val[1], 以此類推*/
inline CvScalar cvScalar( double val0, double val1,
                           double val2, double val3);

{  CvScalar  arr;
    
    arr.val[4] = {val0,val1,val2,val3};
  
    reture arr;}
/* 構造函數:用val0123初始化全部val[0]...val[3] */
inline CvScalar cvScalarAll( double val0123 );
 
  { CvScalar arr;
 
     arr.val[4] = {val0123,val0123,val0123,val0123,};

     reture arr;}
/* 構造函數:用val0初始化val[0],用0初始化val[1],val[2],val[3] */
inline CvScalar cvRealScalar( double val0 );

    { CvScalar arr;
       
       arr.val[4] = {val0};
   
       reture arr;}

CvTermCriteria

迭代算法的終止準則

#define CV_TERMCRIT_ITER    1
#define CV_TERMCRIT_NUMBER  CV_TERMCRIT_ITER
#define CV_TERMCRIT_EPS     2

typedef struct CvTermCriteria
 {
  int    type;  /* CV_TERMCRIT_ITER 和CV_TERMCRIT_EPS二值之一,或者兩者的組合 */
  int    max_iter; /* 最大迭代次數 */
  double epsilon; /* 結果的精確性 */
 }
 CvTermCriteria;
/* 構造函數 */
inline  CvTermCriteria  cvTermCriteria( int type, int max_iter, double epsilon );
/* 在知足max_iter和epsilon的條件下檢查終止準則並將其轉換使得type=CV_TERMCRIT_ITER+CV_TERMCRIT_EPS */
CvTermCriteria cvCheckTermCriteria( CvTermCriteria criteria,
                                    double default_eps,
                                    int default_max_iters );

CvMat

多通道矩陣

typedef struct CvMat
 {
  int type; /* CvMat 標識 (CV_MAT_MAGIC_VAL), 元素類型和標記 */
  int step; /* 以字節爲單位的行數據長度*/
  int* refcount; /* 數據引用計數 */
  union
   {
    uchar* ptr;
    short* s;
    int* i;
    float* fl;
    double* db;
   } data; /* data 指針 */
  #ifdef __cplusplus
  union
   {
     int rows;
     int height;
   };
  union
   {
     int cols;
     int width;
   };
  #else
   int rows; /* 行數 */
   int cols; /* 列數*/
  #endif
 } CvMat;

CvMatND

多維、多通道密集數組

typedef struct CvMatND
    {
        int type; /* CvMatND 標識(CV_MATND_MAGIC_VAL), 元素類型和標號*/
        int dims; /* 數組維數 */

        int* refcount; /* 數據參考計數 */

        union
        {
            uchar* ptr;
            short* s;
            int* i;
            float* fl;
            double* db;
        } data; /* data 指針*/

        /* 每維的數據結構 (元素號,以字節爲單位的元素之間的距離)是配套定義的 */
        struct
        {
            int size;
            int step;
        }
        dim[CV_MAX_DIM];

    } CvMatND;

 

CvSparseMat

多維、多通道稀疏數組

typedef struct CvSparseMat
    {
        int type; /* CvSparseMat 標識 (CV_SPARSE_MAT_MAGIC_VAL), 元素類型和標號 */
        int dims; /* 維數 */
        int* refcount; /* 參考數量 - 未用 */
        struct CvSet* heap; /* HASH表節點池 */
        void** hashtable; /* HASH表:每一個入口有一個節點列表,有相同的 "以HASH大小爲模板的HASH值" */
        int hashsize; /* HASH表大小 */
        int total; /* 稀疏數組的節點數 */
        int valoffset; /* 數組節點值在字節中的偏移 */
        int idxoffset; /* 數組節點索引在字節中的偏移 */
        int size[CV_MAX_DIM]; /*維大小 */

    } CvSparseMat;

 

IplImage

IPL 圖像頭

typedef struct _IplImage
    {
        int  nSize;         /* IplImage大小,=sizeof(IplImage)*/
        int  ID;            /* 版本 (=0)*/
        int  nChannels;     /* 大多數OPENCV函數支持1,2,3 或 4 個通道 */
        int  alphaChannel;  /* 被OpenCV忽略 */
        int  depth;         /* 像素的位深度: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,
                               IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F 可支持 */
        char colorModel[4]; /* 被OpenCV忽略 */
        char channelSeq[4]; /* 被OpenCV忽略 */
        int  dataOrder;     /* 0 - 交叉存取顏色通道,對三通道RGB圖像,像素存儲順序爲BGR BGR BGR ... BGR;
                                     1 - 分開的顏色通道,對三通道RGB圖像,像素存儲順序爲RRR...R GGG...G BBB...B。
                                  cvCreateImage只能建立交叉存取圖像 */
        int  origin;        /* 0 - 頂—左結構,
                               1 - 底—左結構 (Windows bitmaps 風格) */
        int  align;         /* 圖像行排列 (4 or 8). OpenCV 忽略它,使用 widthStep 代替 */
        int  width;         /* 圖像寬像素數 */
        int  height;        /* 圖像高像素數*/
        struct _IplROI *roi;/* 圖像感興趣區域. 當該值非空只對該區域進行處理 */
        struct _IplImage *maskROI; /* 在 OpenCV中必須置NULL */
        void  *imageId;     /* 同上*/
        struct _IplTileInfo *tileInfo; /*同上*/
        int  imageSize;     /* 圖像數據大小(在交叉存取格式下imageSize=image->height*image->widthStep),單位字節*/
        char *imageData;  /* 指向排列的圖像數據 */
        int  widthStep;   /* 排列的圖像行大小,以字節爲單位 */
        int  BorderMode[4]; /* 邊際結束模式, 被OpenCV忽略 */
        int  BorderConst[4]; /* 同上 */
        char *imageDataOrigin; /* 指針指向一個不一樣的圖像數據結構(不是必須排列的),是爲了糾正圖像內存分配準備的 */
    }
    IplImage;

IplImage結構來自於 Intel Image Processing Library(是其自己所具備的)。OpenCV 只支持其中的一個子集:

  • alphaChannel 在OpenCV中被忽略。
  • colorModel 和channelSeq 被OpenCV忽略。OpenCV顏色轉換的惟一函數 cvCvtColor把原圖像的顏色空間的目標圖像的顏色空間做爲一個參數。
  • dataOrder 必須是IPL_DATA_ORDER_PIXEL (顏色通道是交叉存取),然而平面圖像的被選擇通道能夠被處理,就像COI(感興趣的通道)被設置過同樣。
  • align 是被OpenCV忽略的,而用 widthStep 去訪問後繼的圖像行。
  • 不支持maskROI 。處理MASK的函數把他看成一個分離的參數。MASK在 OpenCV 裏是 8-bit,然而在 IPL他是 1-bit。
  • tileInfo 不支持。
  • BorderMode和BorderConst是不支持的。每一個 OpenCV 函數處理像素的鄰近的像素,一般使用單一的固定代碼邊際模式。

除了上述限制,OpenCV處理ROI有不一樣的要求。要求原圖像和目標圖像的尺寸或 ROI的尺寸必須(根據不一樣的操做,例如cvPyrDown 目標圖像的寬(高)必須等於原圖像的寬(高)除以2 ±1)精確匹配,而IPL處理交叉區域,如圖像的大小或ROI大小多是徹底獨立的。

CvArr

不肯定數組

typedef void CvArr;

CvArr* 僅僅是被用於做函數的參數,用於指示函數接收的數組類型能夠不止一個,如 IplImage*, CvMat* 甚至 CvSeq*. 最終的數組類型是在運行時經過分析數組頭的前4 個字節判斷。

數組操做

初始化

CreateImage

建立頭並分配數據

IplImage* cvCreateImage( CvSize size, int depth, int channels );

size

圖像寬、高.

depth 

圖像元素的位深度,能夠是下面的其中之一:

IPL_DEPTH_8U - 無符號8位整型

IPL_DEPTH_8S - 有符號8位整型

IPL_DEPTH_16U - 無符號16位整型

IPL_DEPTH_16S - 有符號16位整型

IPL_DEPTH_32S - 有符號32位整型

IPL_DEPTH_32F - 單精度浮點數

IPL_DEPTH_64F - 雙精度浮點數

channels 

每一個元素(像素)的顏色通道數量.能夠是 1, 2, 3 或 4.通道是交叉存取的,例如一般的彩色圖像數據排列是:

b0 g0 r0 b1 g1 r1 ...

雖然一般 IPL 圖象格式能夠存貯非交叉存取的圖像,而且一些OpenCV 也能處理他, 可是這個函數只能建立交叉存取圖像.

函數 cvCreateImage 建立頭並分配數據,這個函數是下列的縮寫型式

header = cvCreateImageHeader(size,depth,channels);

cvCreateData(header); //只是建立空間,並不會初始化空間內的數據

CreateImageHeader

分配,初始化,而且返回 IplImage結構

IplImage* cvCreateImageHeader( CvSize size, int depth, int channels );

size

圖像寬、高.

depth

像深 (見 CreateImage).

channels

通道數 (見 CreateImage).

函數 cvCreateImageHeader 分配, 初始化, 而且返回 IplImage結構. 這個函數類似於:

  iplCreateImageHeader( channels, 0, depth,

                        channels == 1 ? "GRAY" : "RGB",

                        channels == 1 ? "GRAY" : channels == 3 ? "BGR" :

                        channels == 4 ? "BGRA" : "",

                        IPL_DATA_ORDER_PIXEL, IPL_ORIGIN_TL, 4,

                        size.width, size.height,

                        0,0,0,0);

然而IPL函數不是做爲默認的 (見 CV_TURN_ON_IPL_COMPATIBILITY 宏)

ReleaseImageHeader

釋放頭

void cvReleaseImageHeader( IplImage** image );

image 

雙指針指向頭內存分配單元.

函數 cvReleaseImageHeader 釋放頭. 類似於

if( image )

{

    iplDeallocate( *image, IPL_IMAGE_HEADER | IPL_IMAGE_ROI );

    *image = 0;

}

然而IPL函數不是做爲默認的 (見 CV_TURN_ON_IPL_COMPATIBILITY 宏)

ReleaseImage

釋放頭和圖像數據

void cvReleaseImage( IplImage** image );

image 

雙指針指向圖像內存分配單元。

函數 cvReleaseImage 釋放頭和圖像數據,類似於:

if( *image )

{

    cvReleaseData( *image );

    cvReleaseImageHeader( image );

}

InitImageHeader

初始化被用圖分配的圖像頭

IplImage* cvInitImageHeader( IplImage* image, CvSize size, int depth,

                             int channels, int origin=0, int align=4 );

image 

被初始化的圖像頭.

size 

圖像的寬高.

depth 

像深(見 CreateImage).

channels 

通道數(見 CreateImage).

origin 

IPL_ORIGIN_TL 或 IPL_ORIGIN_BL.

align 

圖像行排列, 典型的 4 或 8 字節.

函數 cvInitImageHeader 初始化圖像頭結構, 指向用戶指定的圖像而且返回這個指針。

CloneImage

製做圖像的完整拷貝

IplImage* cvCloneImage( const IplImage* image );

image 

原圖像.

函數 cvCloneImage 製做圖像的完整拷貝包括頭、ROI和數據

SetImageCOI

基於給定的值設置感興趣通道

void cvSetImageCOI( IplImage* image, int coi );

image 

圖像頭.

coi 

感興趣通道.

函數 cvSetImageCOI 基於給定的值設置感興趣的通道。值 0 意味着全部的通道都被選定, 1 意味着第一個通道被選定等等。若是 ROI 是 NULL 而且COI!= 0, ROI 被分配. 然而大多數的 OpenCV 函數不支持 COI, 對於這種情況當處理分離圖像/矩陣通道時,能夠拷貝(經過 cvCopy 或cvSplit) 通道來分離圖像/矩陣,處理後若是須要可再拷貝(經過cvCopy 或 cvCvtPlaneToPix)回來.

GetImageCOI

返回感興趣通道號

int cvGetImageCOI( const IplImage* image );

image 

圖像頭.

函數cvGetImageCOI 返回圖像的感興趣通道(當全部的通道都被選中返回值是0).

SetImageROI

基於給定的矩形設置'感興趣'區域

void cvSetImageROI( IplImage* image, CvRect rect );

image 

圖像.

rect 

ROI 矩形.

函數 cvSetImageROI 基於給定的矩形設置圖像的 ROI(感興趣區域) . 若是ROI是NULL 而且參數RECT的值不等於整個圖像, ROI被分配. 不像 COI, 大多數的 OpenCV 函數支持 ROI 而且處理它就像它是一個分離的圖像 (例如, 全部的像素座標從ROI的左上角或左下角(基於圖像的結構)計算。

ResetImageROI

釋放圖像的ROI

void cvResetImageROI( IplImage* image );

image 

圖像頭.

函數 cvResetImageROI 釋放圖像 ROI. 釋放以後整個圖像被認爲是所有被選中的。類似的結果能夠經過下述辦法

cvSetImageROI( image, cvRect( 0, 0, image->width, image->height ));

cvSetImageCOI( image, 0 );

可是後者的變量不分配 image->roi.

 

GetImageROI

返回圖像的 ROI 座標

CvRect cvGetImageROI( const IplImage* image );

image 

圖像頭.

函數 cvGetImageROI 返回圖像ROI 座標. 若是沒有ROI則返回矩形值爲 cvRect(0,0,image->width,image->height)

 

CreateMat

建立矩陣

CvMat* cvCreateMat( int rows, int cols, int type );

rows 

矩陣行數。

cols 

矩陣列數。

type 

矩陣元素類型。 一般以 CV_<比特數>(S|U|F)C<通道數>型式描述, 例如:

   CV_8UC1 意思是一個8-bit 無符號單通道矩陣, CV_32SC2 意思是一個32-bit 有符號二個通道的矩陣。

函數 cvCreateMat 爲新的矩陣分配頭和下面的數據,而且返回一個指向新建立的矩陣的指針。是下列操做的縮寫型式:

CvMat* mat = cvCreateMatHeader( rows, cols, type );

cvCreateData( mat );

矩陣按行存貯。全部的行以4個字節對齊。

CreateMatHeader

建立新的矩陣頭

CvMat* cvCreateMatHeader( int rows, int cols, int type );

rows

   矩陣行數.

cols

矩陣列數.

type

矩陣元素類型(見 cvCreateMat).

函數 cvCreateMatHeader 分配新的矩陣頭而且返回指向它的指針. 矩陣數據可被進一步的分配,使用cvCreateData 或經過 cvSetData明確的分配數據.

ReleaseMat

刪除矩陣

void cvReleaseMat( CvMat** mat );

mat

雙指針指向矩陣.

函數cvReleaseMat 縮減矩陣數據參考計數而且釋放矩陣頭 :

if( *mat )

    cvDecRefData( *mat );

cvFree( (void**)mat );

InitMatHeader

初始化矩陣頭

CvMat* cvInitMatHeader( CvMat* mat, int rows, int cols, int type,

                       void* data=NULL, int step=CV_AUTOSTEP );

mat

指針指向要被初始化的矩陣頭.

rows

矩陣的行數.

cols

矩陣的列數.

type

矩陣元素類型.

data

可選的,將指向數據指針分配給矩陣頭.

step

排列後的數據的整個行寬,默認狀態下,使用STEP的最小可能值。也就是說默認狀況下假定矩陣的行與行之間無隙.

函數 cvInitMatHeader 初始化已經分配了的 CvMat 結構. 它能夠被OpenCV矩陣函數用於處理原始數據。

例如, 下面的代碼計算通用數組格式存貯的數據的矩陣乘積.

計算兩個矩陣的積

double a[] = { 1, 2, 3, 4,

               5, 6, 7, 8,

               9, 10, 11, 12 };

 

double b[] = { 1, 5, 9,

               2, 6, 10,

               3, 7, 11,

               4, 8, 12 };

 

double c[9];

CvMat Ma, Mb, Mc ;

 

cvInitMatHeader( &Ma, 3, 4, CV_64FC1, a );

cvInitMatHeader( &Mb, 4, 3, CV_64FC1, b );

cvInitMatHeader( &Mc, 3, 3, CV_64FC1, c );

 

cvMatMulAdd( &Ma, &Mb, 0, &Mc );

// c 數組存貯 a(3x4) 和 b(4x3) 矩陣的積

Mat

初始化矩陣的頭(輕磅變量)

CvMat cvMat( int rows, int cols, int type, void* data=NULL );

rows

矩陣行數

cols

列數.

type

元素類型(見CreateMat).

data

可選的分配給矩陣頭的數據指針 .

函數 cvMat 是個一快速內連函數,替代函數 cvInitMatHeader. 也就是說它至關於:

CvMat mat;

cvInitMatHeader( &mat, rows, cols, type, data, CV_AUTOSTEP );

 

CloneMat

建立矩陣拷貝

CvMat* cvCloneMat( const CvMat* mat );

mat

輸入矩陣.

函數 cvCloneMat 建立輸入矩陣的一個拷貝而且返回 該矩陣的指針.

CreateMatND

建立多維密集數組

CvMatND* cvCreateMatND( int dims, const int* sizes, int type );

dims

數組維數. 但不準超過 CV_MAX_DIM (默認=32,但這個默認值可能在編譯時被改變 )的定義

sizes

數組的維大小.

type

數組元素類型. 與 CvMat相同

函數cvCreateMatND 分配頭給多維密集數組而且分配下面的數據,返回指向被建立數組的指針 . 是下列的縮減形式:

CvMatND* mat = cvCreateMatNDHeader( dims, sizes, type );

cvCreateData( mat );

矩陣按行存貯. 全部的行以4個字節排列。.

 

CreateMatNDHeader

建立新的數組頭

CvMatND* cvCreateMatNDHeader( int dims, const int* sizes, int type );

dims

數組維數.

sizes

維大小.

type

數組元素類型. 與 CvMat相同

函數cvCreateMatND 分配頭給多維密集數組。數組數據能夠用 cvCreateData 進一步的被分配或利用cvSetData由用戶明確指定.

ReleaseMatND

刪除多維數組

void cvReleaseMatND( CvMatND** mat );

mat

指向數組的雙指針.

函數 cvReleaseMatND 縮減數組參考計數並釋放數組頭:

if( *mat )

    cvDecRefData( *mat );

cvFree( (void**)mat );

InitMatNDHeader

初始化多維數組頭

CvMatND* cvInitMatNDHeader( CvMatND* mat, int dims, const int* sizes, int type, void* data=NULL );

mat

指向要被出初始化的數組頭指針.

dims

數組維數.

sizes

維大小.

type

數組元素類型. 與 CvMat相同

data

可選的分配給矩陣頭的數據指針.

函數 cvInitMatNDHeader 初始化 用戶指派的CvMatND 結構.

CloneMatND

建立多維數組的完整拷貝

CvMatND* cvCloneMatND( const CvMatND* mat );

mat

輸入數組

函數 cvCloneMatND 建立輸入數組的拷貝並返回指針.

DecRefData

縮減數組數據的引用計數

void cvDecRefData( CvArr* arr );

arr

數組頭.

若是引用計數指針非NULL,函數 cvDecRefData 縮減CvMat 或CvMatND 數據的引用計數,若是計數到0就刪除數據。在當前的版本中只有當數據是用cvCreateData 分配的引用計數纔會是非NULL。在其餘的狀況下好比:

·       使用cvSetData指派外部數據給矩陣頭;

·       表明部分大的矩陣或圖像的矩陣頭;

·       是從圖像頭或N維矩陣頭轉換過來的矩陣頭,

在這些狀況下引用計數被設置成NULL所以不會被縮減。 不管數據是否被刪除,數據指針和引用計數指針都將被這個函數清空。

IncRefData

增長數組數據的引用計數

int cvIncRefData( CvArr* arr );

arr

數組頭.

函數 cvIncRefData 增長 CvMat 或 CvMatND 數據引用計數,若是引用計數非空返回新的計數值 不然返回0。

CreateData

分配數組數據

void cvCreateData( CvArr* arr );

arr

數組頭.

函數 cvCreateData 分配圖像,矩陣或多維數組數據. 對於矩陣類型使用OpenCV的分配函數,對於 IplImage類型若是CV_TURN_ON_IPL_COMPATIBILITY沒有被調用也是可使用這種方法的反之使用 IPL 函數分配數據

ReleaseData

釋放數組數據

void cvReleaseData( CvArr* arr );

arr

數組頭

函數cvReleaseData 釋放數組數據. 對於 CvMat 或 CvMatND 結構只需調用 cvDecRefData(), 也就是說這個函數不能刪除外部數據。見 cvCreateData.

SetData

指派用戶數據給數組頭

void cvSetData( CvArr* arr, void* data, int step );

arr

數組頭.

data

用戶數據.

step

整行字節長.

函數cvSetData 指派用戶數據給數組頭. 頭應該已經使用 cvCreate*Header, cvInit*Header 或 cvMat (對於矩陣)初始化過.

GetRawData

返回數組的底層信息

void cvGetRawData( const CvArr* arr, uchar** data,

                   int* step=NULL, CvSize* roi_size=NULL );

arr

數組頭.

data

輸出指針,指針指向整個圖像的結構或ROI

step

輸出行字節長

roi_size

輸出ROI尺寸

函數 cvGetRawData 添充給輸出變量數組的底層信息。全部的輸出參數是可選的, 所以這些指針可設爲NULL。若是數組是設置了ROI的 IplImage 結構, ROI參數被返回。

注意:輸出指針指向數組頭的對應的內存,不能釋放。建議用memcpy。

接下來的例子展現怎樣利用這個函數去訪問數組元素。

使用 GetRawData 計算單通道浮點數組的元素絕對值。

float* data;

int step;

 

CvSize size;

int x, y;

 

cvGetRawData( array, (uchar**)&data, &step, &size );

step /= sizeof(data[0]);

 

for( y = 0; y < size.height; y++, data += step )

    for( x = 0; x < size.width; x++ )

        data[x] = (float)fabs(data[x]);

GetMat

從不肯定數組返回矩陣頭

CvMat* cvGetMat( const CvArr* arr, CvMat* header, int* coi=NULL, int allowND=0 );

arr

輸入數組.

header

指向 CvMat結構的指針,做爲臨時緩存 .

coi

可選的輸出參數,用於輸出COI.

allowND

若是非0,函數就接收多維密集數組 (CvMatND*)而且返回 2D (若是 CvMatND 是二維的)或 1D 矩陣(當 CvMatND 是一維或多於二維). 數組必須是連續的.

函數 cvGetMat從輸入的數組生成矩陣頭,輸入的數組能夠是 - CvMat結構, IplImage結構 或多維密集數組 CvMatND* (後者只有當 allowND != 0時纔可使用) . 若是是矩陣函數只是返回指向矩陣的指針.若是是 IplImage* 或 CvMatND* 函數用當前圖像的ROI初始化頭結構而且返回指向這個臨時結構的指針。由於CvMat不支持COI,因此他們的返回結果是不一樣的.

這個函數提供了一個簡單的方法,用同一代碼處理 IplImage 和 CvMat二種數據類型。這個函數的反向轉換能夠用 cvGetImage將 CvMat 轉換成 IplImage .

輸入的數組必須有已分配好的底層數據或附加的數據,不然該函數將調用失敗若是輸入的數組是IplImage 格式,使用平面式數據編排並設置了COI,函數返回的指針指向被選定的平面並設置COI=0.利用OPENCV函數對於多通道平面編排圖像能夠處理每一個平面。

GetImage

從不肯定數組返回圖像頭

IplImage* cvGetImage( const CvArr* arr, IplImage* image_header );

arr

輸入數組.

image_header

指向IplImage結構的指針,該結構存貯在一個臨時緩存 .

函數 cvGetImage 從輸出數組得到圖頭,該數組能夠是矩陣- CvMat*, 或圖像 - IplImage*。 若是是圖像的話函數只是返回輸入參數的指針,若是是 CvMat* 的話函數用輸入參數矩陣初始化圖像頭。所以若是咱們把 IplImage 轉換成 CvMat 而後再轉換 CvMat 回 IplImage,若是ROI被設置過了咱們可能會得到不一樣的頭,這樣一些計算圖像跨度的IPL函數就會失敗。

CreateSparseMat

建立稀疏數組

CvSparseMat* cvCreateSparseMat( int dims, const int* sizes, int type );

dims

數組維數。相對於密集型矩陣,稀疏數組的維數是不受限制的(最多可達 216)。

sizes

數組的維大小。

type

數組元素類型,見 CvMat。

函數 cvCreateSparseMat 分配多維稀疏數組。剛初始化的數組不含元素,所以cvGet*D 或 cvGetReal*D函數對全部索引都返回0。

ReleaseSparseMat

刪除稀疏數組

void cvReleaseSparseMat( CvSparseMat** mat );

mat

雙指針指向數組。

函數 cvReleaseSparseMat釋放稀疏數組並清空數組指針

CloneSparseMat

建立稀疏數組的拷貝

CvSparseMat* cvCloneSparseMat( const CvSparseMat* mat );

mat

輸入數組。

函數 cvCloneSparseMat 建立輸入數組的拷貝並返回指向這個拷貝的指針。

獲取元素和數組子集

GetSubRect

返回輸入的圖像或矩陣的矩形數組子集的矩陣頭

CvMat* cvGetSubRect( const CvArr* arr, CvMat* submat, CvRect rect );

arr

輸入數組。

submat

指向矩形數組子集矩陣頭的指針。

rect

以0座標爲基準的ROI。

函數 cvGetSubRect 根據指定的數組矩形返回矩陣頭,換句話說,函數容許像處理一個獨立數組同樣處理輸入數組的一個指定子矩形。函數在處理時要考慮進輸入數組的ROI,所以數組的ROI是實際上被提取的。

GetRow, GetRows

返回數組的一行或在必定跨度內的行

CvMat* cvGetRow( const CvArr* arr, CvMat* submat, int row );

CvMat* cvGetRows( const CvArr* arr, CvMat* submat, int start_row, int end_row, int delta_row=1 );

arr

輸入數組。

submat

指向返回的子數組頭的指針。

row

被選定行的索引下標,索引下標從0開始。

start_row

跨度的開始行(包括此行)索引下標,索引下標從0開始。

end_row

跨度的結束行(不包括此行)索引下標,索引下標從0開始。

delta_row

在跨度內的索引下標跨步,從開始行到結束行每隔delta_row行提取一行。

函數GetRow 和 GetRows 返回輸入數組中指定的一行或在必定跨度內的行對應的數組頭。 注意GetRow 其實是 如下cvGetRows調用的簡寫:

cvGetRow( arr, submat, row ) ~ cvGetRows( arr, submat, row, row + 1, 1 );

GetCol, GetCols

返回數組的一列或必定跨度內的列

CvMat* cvGetCol( const CvArr* arr, CvMat* submat, int col );

CvMat* cvGetCols( const CvArr* arr, CvMat* submat, int start_col, int end_col );

arr

輸入數組。

submat

指向結果子數組頭的指針。

col

被選定列的索引下標,索引下標從0開始。

start_col

跨度的開始列(包括該列)索引下標,索引下標從0開始。

end_col

跨度的結束列(不包括該列)索引下標,索引下標從0開始。

函數 GetCol 和 GetCols 根據指定的列/列跨度返回對應的數組頭。注意GetCol 其實是如下 cvGetCols調用的簡寫形式:

cvGetCol( arr, submat, col ); // ~ cvGetCols( arr, submat, col, col + 1 );

GetDiag

返回一個數組對角線

CvMat* cvGetDiag( const CvArr* arr, CvMat* submat, int diag=0 );

arr

輸入數組.

submat

指向結果子集的頭指針.

diag

數組對角線。0是主對角線,-1是主對角線上面對角線,1是主對角線下對角線,以此類推。

函數 cvGetDiag 根據指定的diag參數返回數組的對角線頭。

GetSize

返回矩陣或圖像ROI的大小

CvSize cvGetSize( const CvArr* arr );

arr

數組頭。

函數 cvGetSize 返回圖像或矩陣的行數和列數,若是是圖像就返回ROI的大小。

InitSparseMatIterator

初始化稀疏數組元素迭代器

CvSparseNode* cvInitSparseMatIterator( const CvSparseMat* mat,

                                       CvSparseMatIterator* mat_iterator );

mat

輸入的數組.

mat_iterator

被初始化的迭代器.

函數 cvInitSparseMatIterator 初始化稀疏數組元素的迭代器而且返回指向第一個元素的指針,若是數組爲空則返回NULL。

GetNextSparseNode

初始化稀疏數組元素迭代器

CvSparseNode* cvGetNextSparseNode( CvSparseMatIterator* mat_iterator );

mat_iterator

稀疏數組的迭代器

函數cvGetNextSparseNode 移動迭代器到下一個稀疏矩陣元素並返回指向他的指針。在當前的版本不存在任何元素的特殊順序,由於元素是按HASH表存貯的下面的列子描述怎樣在稀疏矩陣上迭代 :

利用cvInitSparseMatIterator 和cvGetNextSparseNode 計算浮點稀疏數組的和。

double sum;

int i, dims = cvGetDims( array );

CvSparseMatIterator mat_iterator;

CvSparseNode* node = cvInitSparseMatIterator( array, &mat_iterator );

 

for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator ))

{

    int* idx = CV_NODE_IDX( array, node ); /* get pointer to the element indices */

    float val = *(float*)CV_NODE_VAL( array, node ); /* get value of the element

                                                      (assume that the type is CV_32FC1) */

    printf( "(" );

    for( i = 0; i < dims; i++ )

        printf( "%4d%s", idx[i], i < dims - 1 ? "," : "): " );

    printf( "%g\n", val );

 

sum += val;

 

 

printf( "\nTotal sum = %g\n", sum );

GetElemType

返回數組元素類型

int cvGetElemType( const CvArr* arr );

arr

輸入數組.

函數 GetElemType 返回數組元素類型就像在cvCreateMat 中討論的同樣:

CV_8UC1 ... CV_64FC4

GetDims, GetDimSize

返回數組維數和他們的大小或者特殊維的大小

int cvGetDims( const CvArr* arr, int* sizes=NULL );

int cvGetDimSize( const CvArr* arr, int index );

arr

輸入數組.

sizes

可選的輸出數組維尺寸向量,對於2D數組第一位是數組行數(高),第二位是數組列數(寬)

index

以0爲基準的維索引下標(對於矩陣0意味着行數,1意味着列數,對於圖象0意味着高,1意味着寬。

函數 cvGetDims 返回維數和他們的大小。若是是 IplImage 或 CvMat 老是返回2,無論圖像/矩陣行數。函數 cvGetDimSize 返回特定的維大小(每維的元素數)。例如,接下來的代碼使用二種方法計算數組元素總數。

// via cvGetDims()

int sizes[CV_MAX_DIM];

int i, total = 1;

int dims = cvGetDims( arr, size );

for( i = 0; i < dims; i++ )

    total *= sizes[i];

 

// via cvGetDims() and cvGetDimSize()

int i, total = 1;

int dims = cvGetDims( arr );

for( i = 0; i < dims; i++ )

    total *= cvGetDimsSize( arr, i );

 

Ptr*D

返回指向特殊數組元素的指針

uchar* cvPtr1D( const CvArr* arr, int idx0, int* type=NULL );

uchar* cvPtr2D( const CvArr* arr, int idx0, int idx1, int* type=NULL );

uchar* cvPtr3D( const CvArr* arr, int idx0, int idx1, int idx2, int* type=NULL );

uchar* cvPtrND( const CvArr* arr, int* idx, int* type=NULL, int create_node=1, unsigned* precalc_hashval=NULL );

arr

輸入數組.

idx0

元素下標的第一個以0爲基準的成員

idx1

元素下標的第二個以0爲基準的成員

idx2

元素下標的第三個以0爲基準的成員

idx

數組元素下標

type

可選的,矩陣元素類型輸出參數

create_node

可選的,爲稀疏矩陣輸入的參數。若是這個參數非零就意味着被須要的元素若是不存在就會被建立。

precalc_hashval

可選的,爲稀疏矩陣設置的輸入參數。若是這個指針非NULL,函數不會從新計算節點的HASH值,而是從指定位置獲取。這種方法有利於提升智能組合數據的操做(TODO: 提供了一個例子)

函數cvPtr*D 返回指向特殊數組元素的指針。數組維數應該與轉遞給函數物下標數相匹配,除了 cvPtr1D 函數,它能夠被用於順序存取的1D,2D或nD密集數組

函數也能夠用於稀疏數組,而且若是被須要的節點不存在函數能夠建立這個節點並設置爲0

就像其它獲取數組元素的函數 (cvGet[Real]*D, cvSet[Real]*D)若是元素的下標超出了範圍就會產生錯誤

Get*D

返回特殊的數組元素

CvScalar cvGet1D( const CvArr* arr, int idx0 );

CvScalar cvGet2D( const CvArr* arr, int idx0, int idx1 );

CvScalar cvGet3D( const CvArr* arr, int idx0, int idx1, int idx2 );

CvScalar cvGetND( const CvArr* arr, int* idx );

arr

輸入數組.

idx0

元素下標第一個以0爲基準的成員

idx1

元素下標第二個以0爲基準的成員

idx2

元素下標第三個以0爲基準的成員

idx

元素下標數組

函數cvGet*D 返回指定的數組元素。對於稀疏數組若是須要的節點不存在函數返回0 (不會建立新的節點)

GetReal*D

返回單通道數組的指定元素

double cvGetReal1D( const CvArr* arr, int idx0 );

double cvGetReal2D( const CvArr* arr, int idx0, int idx1 );

double cvGetReal3D( const CvArr* arr, int idx0, int idx1, int idx2 );

double cvGetRealND( const CvArr* arr, int* idx );

arr

輸入數組,必須是單通道.

idx0

元素下標的第一個成員,以0爲基準

idx1

元素下標的第二個成員,以0爲基準

idx2

元素下標的第三個成員,以0爲基準

idx

元素下標數組

函數cvGetReal*D 返回單通道數組的指定元素,若是數組是多通道的,就會產生運行時錯誤,而 cvGet*D 函數能夠安全的被用於單通道和多通道數組,但他們運行時會有點慢

若是指定的點不存在對於稀疏數組點會返回0(不會建立新的節點)。

mGet

返回單通道浮點矩陣指定元素

double cvmGet( const CvMat* mat, int row, int col );

mat

輸入矩陣.

row

行下標,以0爲基點.

col

列下標,以0爲基點

函數 cvmGet 是 cvGetReal2D對於單通道浮點矩陣的快速替代函數,函數運行比較快速由於它是內連函數 ,這個函數對於數組類型、數組元素類型的檢查做的不多,而且僅在調式模式下檢查數的行和列範圍。

Set*D

修改指定的數組

void cvSet1D( CvArr* arr, int idx0, CvScalar value );

void cvSet2D( CvArr* arr, int idx0, int idx1, CvScalar value );

void cvSet3D( CvArr* arr, int idx0, int idx1, int idx2, CvScalar value );

void cvSetND( CvArr* arr, int* idx, CvScalar value );

arr

輸入數組

idx0

元素下標的第一個成員,以0爲基點

idx1

元素下標的第二個成員,以0爲基點

idx2

元素下標的第三個成員,以0爲基點

idx

元素下標數組

value

指派的值

函數 cvSet*D 指定新的值給指定的數組元素。對於稀疏矩陣若是指定節點不存在函數建立新的節點

SetReal*D

修改指定數組元素值

void cvSetReal1D( CvArr* arr, int idx0, double value );

void cvSetReal2D( CvArr* arr, int idx0, int idx1, double value );

void cvSetReal3D( CvArr* arr, int idx0, int idx1, int idx2, double value );

void cvSetRealND( CvArr* arr, int* idx, double value );

arr

輸入數組.

idx0

元素下標的第一個成員,以0爲基點

idx1

元素下標的第二個成員,以0爲基點

idx2

元素下標的第三個成員,以0爲基點

idx

元素下標數組

value

指派的值

函數 cvSetReal*D 分配新的值給單通道數組的指定元素,若是數組是多通道就會產生運行時錯誤。然而cvSet*D 能夠安全的被用於多通道和單通道數組,只是稍微有點慢。

對於稀疏數組若是指定的節點不存在函數會建立該節點。

mSet

爲單通道浮點矩陣的指定元素賦值。

void cvmSet( CvMat* mat, int row, int col, double value );

mat

矩陣.

row

行下標,以0爲基點.

col

列下標,以0爲基點.

value

矩陣元素的新值

函數cvmSet 是cvSetReal2D 快速替代,對於單通道浮點矩陣由於這個函數是內連的因此比較快,函數對於數組類型、數組元素類型的檢查做的不多,而且僅在調式模式下檢查數的行和列範圍。

 

 

ClearND

清除指定數組元素

void cvClearND( CvArr* arr, int* idx );

arr

輸入數組.

idx

數組元素下標

函數cvClearND 清除指定密集型數組的元素(置0)或刪除稀疏數組的元素 ,若是元素不存在函數不做任何事

拷貝和添加

Copy

拷貝一個數組給另外一個數組

void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL );

src

輸入數組。

dst

輸出數組。

mask

操做掩碼是8比特單通道的數組,它指定了輸出數組中被改變的元素。

函數cvCopy從輸入數組中複製選定的成分到輸出數組:

若是mask(I)!=0,則dst(I)=src(I)。

若是輸入輸出數組中的一個是IplImage類型的話,其ROI和COI將被使用。輸入輸出數組必須是一樣的類型、維數和大小。函數也能夠用來複制散列數組(這種狀況下不支持mask)。

Set

設置數組全部元素爲指定值

void cvSet( CvArr* arr, CvScalar value, const CvArr* mask=NULL );

arr

輸出數組。

value

填充值。

mask

操做掩碼是8比特單通道的數組,它指定了輸出數組中被改變的元素。

函數 cvSet 拷貝數量值到輸出數組的每個被除數選定的元素:

arr(I)=value if mask(I)!=0

若是數組 arr 是 IplImage 類型, 那麼就會使用ROI,但COI不能設置。

SetZero

清空數組

void cvSetZero( CvArr* arr );

#define cvZero cvSetZero

arr

要被清空數組.

函數 cvSetZero 清空數組. 對於密集型號數組(CvMat, CvMatND or IplImage) cvZero(array) 就至關於 cvSet(array,cvScalarAll(0),0), 對於稀疏數組全部的元素都將被刪除.

 

SetIdentity

初始化帶尺度的單位矩陣

void cvSetIdentity( CvArr* mat, CvScalar value=cvRealScalar(1) );

mat

待初始化的矩陣 (不必定是方陣)。

value

賦值給對角線元素的值。

函數 cvSetIdentity 初始化帶尺度的單位矩陣:

arr(i,j)=value 若是 i=j,

不然爲 0

Range

用指定範圍的數來填充矩陣.

void cvRange( CvArr* mat, double start, double end );

mat

即將被初始化的矩陣,必須是指向單通道的32位(整型或浮點型)的矩陣的指針.

start

指定範圍的最小邊界

end

指定範圍的最大邊界

該函數按如下方式初始化矩陣:

arr(i,j)=(end-start)*(i*cols(arr)+j)/(cols(arr)*rows(arr))

例如:如下的代碼將按相應的整型數初始化一維向量:

CvMat* A = cvCreateMat( 1, 10, CV_32S ); cvRange( A, 0, A->cols ); //A將被初始化爲[0,1,2,3,4,5,6,7,8,9]

變換和置換

Reshape

不拷貝數據修改矩陣/圖像形狀

CvMat* cvReshape( const CvArr* arr, CvMat* header, int new_cn, int new_rows=0 );

arr

輸入的數組.

header

被添充的矩陣頭

new_cn

新的通道數.new_cn = 0 意味着不修改通道數

new_rows

新的行數. 若是new_rows = 0保持原行數不修改不然根據 new_cn 值修改輸出數組

函數 cvReshape 初始化 CvMat 頭header 以便於讓頭指向修改後的形狀(但數據保持原樣)-也就是說修改通道數,修改行數或者二者者改變.

例如, 接下來的代碼建立一個圖像緩存、兩個圖像頭,第一個是 320x240x3 圖像第二個是 960x240x1 圖像:

IplImage* color_img = cvCreateImage( cvSize(320,240), IPL_DEPTH_8U, 3 );

CvMat gray_mat_hdr;

IplImage gray_img_hdr, *gray_img;

cvReshape( color_img, &gray_mat_hdr, 1 );

gray_img = cvGetImage( &gray_mat_hdr, &gray_img_hdr );

下一個例子轉換3x3 矩陣成單向量 1x9

CvMat* mat = cvCreateMat( 3, 3, CV_32F );

CvMat row_header, *row;

row = cvReshape( mat, &row_header, 0, 1 );

ReshapeMatND

修改多維數組形狀,拷貝/不拷貝數據

 CvArr* cvReshapeMatND( const CvArr* arr,

                        int sizeof_header, CvArr* header,

                        int new_cn, int new_dims, int* new_sizes );

 

#define cvReshapeND( arr, header, new_cn, new_dims, new_sizes )   \

        cvReshapeMatND( (arr), sizeof(*(header)), (header), \

                        (new_cn), (new_dims), (new_sizes))

arr

輸入數組

sizeof_header

輸出頭的大小,對於IplImage, CvMat 和 CvMatND 各類結構輸出的頭均是不一樣的.

header

被添充的輸出頭.

new_cn

新的通道數,若是new_cn = 0 則通道數保持原樣

new_dims

新的維數. 若是new_dims = 0 則維數保持原樣。

new_sizes

新的維大小.只有當 new_dims=1值被使用,由於要保持數組的總數一致,所以若是 new_dims = 1, new_sizes 是不被使用的

函數cvReshapeMatND 是 cvReshape 的高級版本,它能夠處理多維數組(可以處理通用的圖像和矩陣)而且修改維數,下面的是使用cvReshapeMatND重寫 cvReshape的二個例子 :

IplImage* color_img = cvCreateImage( cvSize(320,240), IPL_DEPTH_8U, 3 );

IplImage gray_img_hdr, *gray_img;

gray_img = (IplImage*)cvReshapeND( color_img, &gray_img_hdr, 1, 0, 0 );

 

...

 

/*second example is modified to convert 2x2x2 array to 8x1 vector */

int size[] = { 2, 2, 2 };

CvMatND* mat = cvCreateMatND( 3, size, CV_32F );

CvMat row_header, *row;

row = cvReshapeND( mat, &row_header, 0, 1, 0 );

Repeat

用原數組管道式添充輸出數組

void cvRepeat( const CvArr* src, CvArr* dst );

src

輸入數組, 圖像或矩陣。

dst

輸出數組,圖像或矩陣

函數cvRepeat 使用被管道化的原數組添充輸出數組:

dst(i,j)=src(i mod rows(src), j mod cols(src))

所以 ,輸出數組可能小於也可能大於輸入數組.

Flip

垂直,水平或即垂直又水平翻轉二維數組

void  cvFlip( const CvArr* src, CvArr* dst=NULL, int flip_mode=0);

#define cvMirror cvFlip

 

src

原數組.

dst

目標責任制數組. 若是 dst = NULL 翻轉是在內部替換.

flip_mode

指定怎樣去翻轉數組。

flip_mode = 0 沿X-軸翻轉, flip_mode > 0 (如 1) 沿Y-軸翻轉, flip_mode < 0 (如 -1) 沿X-軸和Y-軸翻轉.見下面的公式

函數cvFlip 以三種方式之一翻轉數組 (行和列下標是以0爲基點的):

dst(i,j)=src(rows(src)-i-1,j) if flip_mode = 0

dst(i,j)=src(i,cols(src1)-j-1) if flip_mode > 0

dst(i,j)=src(rows(src)-i-1,cols(src)-j-1) if flip_mode < 0

函數主要使用在:

·       垂直翻轉圖像(flip_mode = 0)用於 頂-左和底-左圖像結構的轉換, 主要用於WIN32系統下的視頻操做處理.

·       水平圖像轉換,使用連續的水平轉換和絕對值差檢查垂直軸對稱(flip_mode > 0)

·       水平和垂直同時轉換,用於連續的水平轉換和絕對真理值差檢查中心對稱s(flip_mode < 0)

·       翻轉1維指針數組的順序(flip_mode > 0)

Split

分割多通道數組成幾個單通道數組或者從數組中提取一個通道

void cvSplit( const CvArr* src, CvArr* dst0, CvArr* dst1,

               CvArr* dst2, CvArr* dst3 );

#define cvCvtPixToPlane cvSplit

src

原數組.

dst0...dst3

目標通道

函數 cvSplit 分割多通道數組成分離的單通道數組d。可得到兩種操做模式 . 若是原數組有N通道且前N輸出數組非NULL, 全部的通道都會被從原數組中提取,若是前N個通道只有一個通道非NULL函數只提取該指定通道,不然會產生一個錯誤,餘下的通道(超過前N個通道的以上的)必須被設置成NULL,對於設置了COI的IplImage 結使用cvCopy 也能夠從圖像中提取單通道。

Merge

從幾個單通道數組組合成多通道數組或插入一個單通道數組

void cvMerge( const CvArr* src0, const CvArr* src1,

              const CvArr* src2, const CvArr* src3, CvArr* dst );

#define cvCvtPlaneToPix cvMerge

src0... src3

輸入的通道.

dst

輸出數組.

函數cvMerge 是前一個函數的反向操做。若是輸出數組有N個通道而且前N個輸入通道非NULL,就拷貝全部通道到輸出數組,若是在前N個通道中只有一個單通道非NULL ,只拷貝這個通道到輸出數組,不然 就會產生錯誤。除前N通道之外的餘下的通道必須置NULL。對於設置了COI的 IplImage結構使用 cvCopy也能夠實現向圖像中插入一個通道 。

MixChannels

拷貝輸入數組的若干個通道到輸出數組的某些通道上面.

void cvMixChannels( const CvArr** src, int src_count,

                   CvArr** dst, int dst_count,

                   const int* from_to, int pair_count );

src

輸入數組

src_count

輸入數組的個數

dst

輸出數組

dst_count

輸出數組的個數

from_to

對數的陣列

pair_count

from_to裏面的對數的個數,或者說被拷貝的位面的個數.

RandShuffle

隨機交換數組的元素

void cvRandShuffle( CvArr* mat, CvRNG* rng, double iter_factor=1.);

mat

輸入的矩陣,用來被隨機處理.

rng

隨機數產生器用來隨機交換數組元素.若是爲NULL,一個當前的隨機數發生器將被建立與使用.

iter_factor

相關的參數,用來刻劃交換操做的密度.請看下面的說明.

這個函數在每一個反覆的操做中交換隨機選擇的矩陣裏面的元素(在多通道的數組裏面每一個元素可能包括若干個部分),反覆的次數(也就是交換的對數)等於round(iter_factor*rows(mat)*cols(mat)), 所以若是iter_factor=0,沒有交換產生,若是等於1意味着隨機交換了rows(mat)*cols(mat)對數.

算術,邏輯和比較

LUT

利用查找錶轉換數組

void cvLUT( const CvArr* src, CvArr* dst, const CvArr* lut );

src

元素爲8位的原數組。

dst

與原數組有相同通道數的輸出數組,深度不肯定

lut

有256個元素的查找表;必需要與原輸出數組有相同像深 。

函數cvLUT 使用查找表中的值添充輸出數組. 座標入口來自於原數組,也就是說函數處理每一個元素按以下方式:

dst(I)=lut[src(I)+DELTA]

這裏當src的深度是CV_8U時DELTA=0 ,src的深度是CV_8S時 DELTA=128

ConvertScale

使用線性變換轉換數組

void cvConvertScale( const CvArr* src, CvArr* dst, double scale=1, double shift=0 );

#define cvCvtScale cvConvertScale

#define cvScale  cvConvertScale

#define cvConvert( src, dst )  cvConvertScale( (src), (dst), 1, 0 )

src

輸入數組.

dst

輸出數組

scale

比例因子.

shift

該加數被加到輸入數組元素按比例縮放後獲得的元素上

函數 cvConvertScale 有多個不一樣的目的所以就有多個同義函數(如上面的#define所示)。該函數首先對輸入數組的元素進行比例縮放,而後將shift加到比例縮放後獲得的各元素上,即: dst(I)=src(I)*scale + (shift,shift,...),最後可選的類型轉換將結果拷貝到輸出數組。

多通道的數組對各個通道是獨立處理的。

類型轉換主要用舍入和溢出截斷來完成。也就是若是縮放+轉換後的結果值不能用輸出數組元素類型值精確表達,就設置成在輸出數組數據軸上最接近該數的值。

若是 scale=1, shift=0 就不會進行比例縮放. 這是一個特殊的優化,至關於該函數的同義函數名:cvConvert 。若是原來數組和輸出數組的類型相同,這是另外一種特殊情形,能夠被用於比例縮放和平移矩陣或圖像,此時至關於該函數的同義函數名:cvScale。

ConvertScaleAbs

使用線性變換轉換輸入數組元素成8位無符號整型

void cvConvertScaleAbs( const CvArr* src, CvArr* dst, double scale=1, double shift=0 );

#define cvCvtScaleAbs cvConvertScaleAbs

src

原數組

dst

輸出數組 (深度爲 8u).

scale

比例因子.

shift

原數組元素按比例縮放後添加的值。

函數 cvConvertScaleAbs 與前一函數是相同的,但它是存貯變換結果的絕對值:

dst(I)=abs(src(I)*scale + (shift,shift,...))

函數只支持目標數數組的深度爲 8u (8-bit 無符號) , 對於別的類型函數仿效於cvConvertScale 和 cvAbs 函數的聯合

Add

計算兩個數組中每一個元素的和

void cvAdd( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );

src1

第一個原數組

src2

第二個原數組

dst

輸出數組

mask

操做的覆蓋面, 8-bit單通道數組; 只有覆蓋面指定的輸出數組被修改。

函數 cvAdd 加一個數組到別一個數組中:

dst(I)=src1(I)+src2(I) if mask(I)!=0

除覆蓋面外全部的數組必須有相同的類型相同的大小(或ROI尺寸)。

AddS

計算數量和數組的和

void cvAddS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );

src

原數組.

value

被加入數量

dst

輸出數組

mask

操做的覆蓋面(8-bit單通道數組) ; 只有覆蓋面指定的輸出數組被修改

函數 cvAddS 用數量值與原數組src1的每一個元素想加並存貯結果到

dst(I)=src(I)+value if mask(I)!=0

除覆蓋面外全部數組都必須有相同的類型,相同的大小(或ROI大小)

AddWeighted

計算兩數組的加權值的和

void  cvAddWeighted( const CvArr* src1, double alpha,

                     const CvArr* src2, double beta,

                     double gamma, CvArr* dst );

src1

第一個原數組.

alpha

第一個數組元素的權值

src2

第二個原數組

beta

第二個數組元素的權值

dst

輸出數組

gamma

添加的常數項。

函數 cvAddWeighted 計算兩數組的加權值的和:

dst(I)=src1(I)*alpha+src2(I)*beta+gamma

全部的數組必須有相同的類型相同的大小(或ROI大小)

Sub

計算兩個數組每一個元素的差

void cvSub( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );

src1

第一個原數組

src2

第二個原數組.

dst

輸出數組.

mask

操做覆蓋面( 8-bit 單通道數組); 只有覆蓋面指定的輸出數組被修改

函數cvSub 從一個數組減去別一個數組:

dst(I)=src1(I)-src2(I) if mask(I)!=0

除覆蓋面外全部數組都必須有相同的類型,相同的大小(或ROI大小)

SubS

計算數組和數量之間的差

void cvSubS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );

src

原數組.

value

被減的數量.

dst

輸出數組.

mask

操做覆蓋面( 8-bit 單通道數組); 只有覆蓋面指定的輸出數組被修改

函數 cvSubS 從原數組的每一個元素中減去一個數量:

dst(I)=src(I)-value if mask(I)!=0

除覆蓋面外全部數組都必須有相同的類型,相同的大小(或ROI大小)。

SubRS

計算數量和數組之間的差

void cvSubRS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );

src

第一個原數組。

value

被減的數量

dst

輸出數組

mask

操做覆蓋面( 8-bit 單通道數組); 只有覆蓋面指定的輸出數組被修改

函數 cvSubRS 從一個數量減去原數組的每一個元素:

dst(I)=value-src(I) if mask(I)!=0

除覆蓋面外全部數組都必須有相同的類型,相同的大小(或ROI大小)。

Mul

計算兩個數組中每一個元素的積

void cvMul( const CvArr* src1, const CvArr* src2, CvArr* dst, double scale=1 );

src1

第一個原數組.

src2

第二個原數組.

dst

輸出數組.

scale

設置的比例因子

函數 cvMul 計算兩個數組中每一個元素的積:

dst(I)=scale•src1(I)•src2(I)

全部的數組必須有相同的類型和相同的大小(或ROI大小)

Div

兩個數組每一個元素相除

void cvDiv( const CvArr* src1, const CvArr* src2, CvArr* dst, double scale=1 );

src1

第一個原數組。如該指針爲NULL,假高該數組的全部元素都爲1

src2

第二個原數組。

dst

輸出數組

scale

設置的比例因子

函數 cvDiv 用一個數組除以另外一個數組:

dst(I)=scale•src1(I)/src2(I), if src1!=NULL

dst(I)=scale/src2(I),:  if src1=NULL

全部的數組必須有相同的類型和相同的大小(或ROI大小)

And

計算兩個數組的每一個元素的按位與

void cvAnd( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );

src1

第一個原數組

src2

第二個原數組.

dst

輸出數組

mask

操做覆蓋面( 8-bit 單通道數組); 只有覆蓋面指定的輸出數組被修改

函數 cvAnd 計算兩個數組的每一個元素的按位邏輯與:

dst(I)=src1(I)&src2(I) if mask(I)!=0

對浮點數組按位表示操做是頗有利的。除覆蓋面,全部數組都必須有相同的類型,相同的大小(或ROI大小)。

AndS

計算數組每一個元素與數量之間的按位與

void cvAndS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );

src

原數組.

value

操做中用到的數量

dst

輸出數組

mask

操做覆蓋面( 8-bit 單通道數組); 只有覆蓋面指定的輸出數組被修改

函數 AndS 計算數組中每一個元素與數量之量的按位與:

dst(I)=src(I)&value if mask(I)!=0

在實際操做以前首先把數量類型轉換成與數組相同的類型。對浮點數組按位表示操做是頗有利的。除覆蓋面,全部數組都必須有相同的類型,相同的大小(或ROI大小)。

接下來的例子描述怎樣計算浮點數組元素的絕對值,經過清除最前面的符號位:

float a[] = { -1, 2, -3, 4, -5, 6, -7, 8, -9 };

CvMat A = cvMat( 3, 3, CV_32F, &a );

int i, abs_mask = 0x7fffffff;

cvAndS( &A, cvRealScalar(*(float*)&abs_mask), &A, 0 );

for( i = 0; i < 9; i++ )

    printf("%.1f ", a[i] );

代碼結果是:

1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0

Or

計算兩個數組每一個元素的按位或

void cvOr( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );

src1

第一個原數組

src2

第二個原數組

dst

輸出數組.

mask

操做覆蓋面( 8-bit 單通道數組); 只有覆蓋面指定的輸出數組被修改

函數 cvOr 計算兩個數組每一個元素的按位或:

dst(I)=src1(I)|src2(I)

對浮點數組按位表示操做是頗有利的。除覆蓋面,全部數組都必須有相同的類型,相同的大小(或ROI大小)。

OrS

計算數組中每一個元素與數量之間的按位或

void cvOrS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );

src1

原數組

value

操做中用到的數量

dst

目數組.

mask

操做覆蓋面( 8-bit 單通道數組); 只有覆蓋面指定的輸出數組被修改

函數 OrS 計算數組中每一個元素和數量之間的按位或:

dst(I)=src(I)|value if mask(I)!=0

在實際操做以前首先把數量類型轉換成與數組相同的類型。對浮點數組按位表示操做是頗有利的。除覆蓋面,全部數組都必須有相同的類型,相同的大小(或ROI大小)。

Xor

計算兩個數組中的每一個元素的按位異或

void cvXor( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );

src1

第一個原數組

src2

第二個原數組.

dst

輸出數組

mask

操做覆蓋面( 8-bit 單通道數組); 只有覆蓋面指定的輸出數組被修改

函數 cvXor 計算兩個數組元素的按位異或:

dst(I)=src1(I) src2(I) if mask(I)!=0

對浮點數組按位表示操做是頗有利的。除覆蓋面,全部數組都必須有相同的類型,相同的大小(或ROI大小)。

XorS

計算數組元素與數量之間的按位異或

void cvXorS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );

src

原數組

value

操做中用到的數量

dst

輸出數組.

mask

操做覆蓋面( 8-bit 單通道數組); 只有覆蓋面指定的輸出數組被修改。

函數 XorS 計算數組元素與數量之間的按位異或:

dst(I)=src(I) value if mask(I)!=0

在實際操做以前首先把數量類型轉換成與數組相同的類型。對浮點數組按位表示操做是頗有利的。除覆蓋面,全部數組都必須有相同的類型,相同的大小(或ROI大小)。

下面例子描述怎樣對共軛複數向量轉換,經過轉換前面的符號位:

float a[] = { 1, 0, 0, 1, -1, 0, 0, -1 }; /* 1, j, -1, -j */

CvMat A = cvMat( 4, 1, CV_32FC2, &a );

int i, neg_mask = 0x80000000;

cvXorS( &A, cvScalar( 0, *(float*)&neg_mask, 0, 0 ), &A, 0 );

for( i = 0; i < 4; i++ )

    printf("(%.1f, %.1f) ", a[i*2], a[i*2+1] );

The code should print:

(1.0,0.0) (0.0,-1.0) (-1.0,0.0) (0.0,1.0)

Not

計算數組元素的按位取反

void cvNot( const CvArr* src, CvArr* dst );

src1

原數組

dst

輸出數組

函數不取反每一個數組元素的每一位

dst(I)=~src(I)

Cmp

比較兩個數組元素P

void cvCmp( const CvArr* src1, const CvArr* src2, CvArr* dst, int cmp_op );

src1

第一個原數組

src2

第二個原數組,這兩個數組必須都是單通道數據。

dst

輸出數組必須是 8u 或 8s 類型.

cmp_op

該標識指定要檢查的元素之間的關係:

CV_CMP_EQ - src1(I) "等於" src2(I)

CV_CMP_GT - src1(I) "大於" src2(I)

CV_CMP_GE - src1(I) "大於等於" src2(I)

CV_CMP_LT - src1(I) "小於" src2(I)

CV_CMP_LE - src1(I) "小於等於" src2(I)

CV_CMP_NE - src1(I) "不等於" src2(I)

函數 cvCmp 比較兩個數組的對應元素而且添充輸出數組:

dst(I)=src1(I) op src2(I),

這裏 op 是 '=', '>', '>=', '<', '<=' or '!='.

若是元素之間的關係爲真則設置dst(I)爲 0xff (也就是全部的位都爲 '1') 不然爲0。除了輸出數組全部數組必須是相同的類型相同的大小(或ROI大小)。

CmpS

比較數組的每一個元素與數量的關係

void cvCmpS( const CvArr* src, double value, CvArr* dst, int cmp_op );

src

原數,輸入數組必須是單通道數據。

value

用與數組元素比較的數量值

dst

輸出數組必須是 8u 或 8s 類型.

cmp_op

該標識指定要檢查的元素之間的關係:

CV_CMP_EQ - src1(I) "等於" value

CV_CMP_GT - src1(I) "大於" value

CV_CMP_GE - src1(I) "大於等於" value

CV_CMP_LT - src1(I) "小於" value

CV_CMP_LE - src1(I) "小於等於" value

CV_CMP_NE - src1(I) "不等於" value

函數 cvCmpS 比較數組元素與數量而且添充目標覆蓋面數組:

dst(I)=src(I) op scalar,

這裏 op 是 '=', '>', '>=', '<', '<=' or '!='.

若是元素之間的關係爲真則設置dst(I)爲 0xff (也就是全部的位都爲 '1') 不然爲0。全部的數組必須有相同的大小(或ROI大小)

InRange

檢查數組元素是否在兩個數組之間

void cvInRange( const CvArr* src, const CvArr* lower, const CvArr* upper, CvArr* dst );

src

第一個原數組

lower

包括進的下邊界數組

upper

不包括進的上邊界線數組

dst

輸出數組必須是 8u 或 8s 類型.

函數 cvInRange 對輸入的數組做範圍檢查,對於單通道數組:

dst(I)=lower(I)0 <= src(I)0 < upper(I)0

對二通道數組:

dst(I)=lower(I)0 <= src(I)0 < upper(I)0 &&

       lower(I)1 <= src(I)1 < upper(I)1

以此類推

若是 src(I) 在範圍內dst(I)被設置爲 0xff (每一位都是 '1')不然置0 。 除了輸出數組全部數組必須是相同的類型相同的大小(或ROI大小)。

InRangeS

檢查數組元素是否在兩個數量之間

void cvInRangeS( const CvArr* src, CvScalar lower, CvScalar upper, CvArr* dst );

src

第一個原數組

lower

包括進的下邊界.

upper

不包括進的上邊界

dst

輸出數組必須是 8u 或 8s 類型.

函數 cvInRangeS 檢查輸入數組元素範圍:對於單通道數組:

dst(I)=lower0 <= src(I)0 < upper0

對於雙通道數組以此類推:

dst(I)=lower0 <= src(I)0 < upper0 &&

       lower1 <= src(I)1 < upper1

若是 src(I) 在範圍內dst(I)被設置爲 0xff (每一位都是 '1')不然置0 。全部的數組必須有相同的大小(或ROI大小)

Max

查找兩個數組中每一個元素的較大值

void cvMax( const CvArr* src1, const CvArr* src2, CvArr* dst );

src1

第一個原數組

src2

第二個原數組

dst

輸出數組

函數 cvMax 計算兩個數組中每一個元素的較大值:

dst(I)=max(src1(I), src2(I))

全部的數組必須的一個單通道,相同的數據類型和相同的大小(或ROI大小)

MaxS

查找數組元素與數量之間的較大值

void cvMaxS( const CvArr* src, double value, CvArr* dst );

src

第一個原數組.

value

數量值.

dst

輸出數組

函數 cvMaxS 計算數組元素和數量之間的較大值:

dst(I)=max(src(I), value)

全部數組必須有一個單一通道,相同的數據類型相同的大小(或ROI大小)

 

 

Min

查找兩個數組元素之間 的較小值

void cvMin( const CvArr* src1, const CvArr* src2, CvArr* dst );

src1

第一個原數組

src2

第二個原數組.

dst

輸出數組.

函數cvMin計算兩個數組元素的較小值

dst(I)=min(src1(I),src2(I))

全部數組必須有一個單一通道,相同的數據類型相同的大小(或ROI大小)

MinS

查找數組元素和數量之間的較小值

void cvMinS( const CvArr* src, double value, CvArr* dst );

src

第一個原數組

value

數量值.

dst

輸出數組..

函數 cvMinS 計算數組元素和數量之量的較小值:

dst(I)=min(src(I), value)

全部數組必須有一個單一通道,相同的數據類型相同的大小(或ROI大小)

 

AbsDiff

計算兩個數組差的絕對值

void cvAbsDiff( const CvArr* src1, const CvArr* src2, CvArr* dst );

src1

第一個原數組

src2

第二個原數組

dst

輸出數組

函數 cvAbsDiff 計算兩個數組差的絕對值

dst(I)c = abs(src1(I)c - src2(I)c).

全部數組必須有相同的數據類型相同的大小(或ROI大小)

 

AbsDiffS

計算數組元素與數量之間差的絕對值

void cvAbsDiffS( const CvArr* src, CvArr* dst, CvScalar value );

#define cvAbs(src, dst) cvAbsDiffS(src, dst, cvScalarAll(0))

src

原數組.

dst

輸出數組

value

數量.

函數 cvAbsDiffS 計算數組元素與數量之間差的絕對值

dst(I)c = abs(src(I)c - valuec).

全部數組必須有相同的數據類型相同的大小(或ROI大小)

 

統計

 

CountNonZero

計算非零數組元素個數

int cvCountNonZero( const CvArr* arr );

arr

數組, 必須是單通道數組或者設置COI(感興趣通道)的多通道圖像。

函數 cvCountNonZero 返回arr中非零元素的數目:

result = sumI arr(I)!=0

當IplImage 支持ROI和COI。

Sum

計算數組元素的和

CvScalar cvSum( const CvArr* arr );

arr

數組.

函數 cvSum 獨立地爲每個通道計算數組元素的和 S :

Sc = sumI arr(I)c

若是數組是IplImage類型和設置了COI, 該函數只處理選定的通道並將和存儲到第一個標量成員 (S0)。常見論壇討論貼 cvSum的結果分析

 

Avg

計算數組元素的平均值

CvScalar cvAvg( const CvArr* arr, const CvArr* mask=NULL );

arr

數組.

mask

可選操做掩模

函數 cvAvg 獨立地爲每個通道計算數組元素的平均值 M :  

若是數組是 IplImage 類型和設置 COI , 該函數只處理選定的通道並將和存儲到第一個標量成員 (S0)。

 

 

AvgSdv

計算數組元素的平均值和標準差

void cvAvgSdv( const CvArr* arr, CvScalar* mean, CvScalar* std_dev, const CvArr* mask=NULL );

arr

數組

mean

指向平均值的指針, 若是不須要的話能夠爲空( NULL)。

std_dev

指向標準差的指針。

mask

可選操做掩模。

函數 cvAvgSdv 獨立地爲每個通道計算數組元素的平均值和標準差:

 若是數組是 IplImage 類型和 設置了COI ,該函數只處理選定的通道並將平均值和標準差存儲到第一個輸出標量成員 (mean0 和 std-dev0)。

MinMaxLoc

查找數組和子數組的全局最小值和最大值

void cvMinMaxLoc( const CvArr* arr, double* min_val, double* max_val,

                  CvPoint* min_loc=NULL, CvPoint* max_loc=NULL, const CvArr* mask=NULL );

arr

輸入數組, 單通道或者設置了 COI 的多通道。

min_val

指向返回的最小值的指針。

max_val

指向返回的最大值的指針。

min_loc

指向返回的最小值的位置指針。

max_loc

指向返回的最大值的位置指針。

mask

選擇一個子數組的操做掩模。

函數 MinMaxLoc 查找元素中的最小值和最大值以及他們的位置。函數在整個數組、或選定的ROI區域(對IplImage)或當MASK不爲NULL時指定的數組區域中,搜索極值 。若是數組不止一個通道,它就必須是設置了 COI 的 IplImage 類型。 若是是多維數組 min_loc->x 和 max_loc->x 將包含極值的原始位置信息 (線性的)。

 

Norm

計算數組的絕對範數, 絕對差分範數或者相對差分範數

double cvNorm( const CvArr* arr1, const CvArr* arr2=NULL, int norm_type=CV_L2, const CvArr* mask=NULL );

arr1

第一輸入圖像

arr2

第二輸入圖像 ,若是爲空(NULL), 計算 arr1 的絕對範數,不然計算 arr1-arr2 的絕對範數或者相對範數。

normType

範數類型,參見「討論」。

mask

可選操做掩模。

若是 arr2 爲空(NULL),函數 cvNorm 計算 arr1 的絕對範數:

norm = ||arr1||C = maxI abs(arr1(I)), 若是 normType = CV_C

norm = ||arr1||L1 = sumI abs(arr1(I)), 若是 normType = CV_L1

norm = ||arr1||L2 = sqrt( sumI arr1(I)2), 若是 normType = CV_L2


若是 arr2 不爲空(NULL), 該函數計算絕對差分範數或者相對差分範數:

norm = ||arr1-arr2||C = maxI abs(arr1(I)-arr2(I)), 若是 normType = CV_C

norm = ||arr1-arr2||L1 = sumI abs(arr1(I)-arr2(I)), 若是 normType = CV_L1

norm = ||arr1-arr2||L2 = sqrt( sumI (arr1(I)-arr2(I))2 ), 若是 normType = CV_L2

或者

norm = ||arr1-arr2||C/||arr2||C, 若是 normType = CV_RELATIVE_C

norm = ||arr1-arr2||L1/||arr2||L1, 若是 normType = CV_RELATIVE_L1

norm = ||arr1-arr2||L2/||arr2||L2, 若是 normType = CV_RELATIVE_L2

函數 Norm 返回計算所得的範數。多通道數組被視爲單通道處理,所以,全部通道的結果是結合在一塊兒的。

 

Reduce

簡化一個矩陣成爲一個向量

cvReduce( const CvArr* src, CvArr* dst, int dim, int op=CV_REDUCE_SUM);

src

輸入矩陣

dst

輸出的經過處理輸入矩陣的全部行/列而獲得的單行/列向量

dim

矩陣被簡化後的維數索引.0意味着矩陣被處理成一行,1意味着矩陣被處理成爲一列,-1時維數將根據輸出向量的大小自動選擇.

op

簡化操做的方式,能夠有如下幾種取值:

CV_REDUCE_SUM-輸出是矩陣的全部行/列的和.

CV_REDUCE_AVG-輸出是矩陣的全部行/列的平均向量.

CV_REDUCE_MAX-輸出是矩陣的全部行/列的最大值.

CV_REDUCE_MIN-輸出是矩陣的全部行/列的最小值.

這個函數經過把矩陣的每行/列看成一維向量並對其作某種特殊的操做將一個矩陣簡化成爲一個向量.例如,這個函數能夠用於計算一個光柵圖象的水平或者垂直投影.在取值爲CV_REDUCE_AVG與CV_REDUCE_SUM的狀況下輸出可能有很大的位深度用於維持準確性,這兩種方式也適合於處理多通道數組.

注意,對於CV_REDUCE_SUM和CV_REDUCE_AVG方式來講,輸入和輸出的位數定義有以下關係

輸入:CV_8U 輸出:CV_32S CV_32F

輸入:CV_16U 輸出:CV_32F CV_64F

輸入:CV_16S 輸出:CV_32F CV_64F

輸入:CV_32F 輸出: CV_32F CV_64F

輸入:CV_64F 輸出: CV_64F

而對於CV_REDUCE_MAX和CV_REDUCE_MIN方式來講,輸入和輸出的位數必須一致

線性代數

DotProduct

用歐幾里得準則計算兩個數組的點積

double cvDotProduct( const CvArr* src1, const CvArr* src2 );

src1

第一輸入數組。

src2

第二輸入數組。

函數 cvDotProduct 計算並返回兩個數組的歐幾里得點積。

src1•src2 = sumI(src1(I)*src2(I))

若是是多通道數組,全部通道的結果是累加在一塊兒的。特別地, cvDotProduct(a,a),將返回 ||a||2 ,這裏 a 是一個復向量。 該函數能夠處理多通道數組,逐行或逐層等等。

Normalize

根據某種範數或者數值範圍歸一化數組.

void cvNormalize( const CvArr* src, CvArr* dst,

                 double a=1, double b=0, int norm_type=CV_L2,

                 const CvArr* mask=NULL );

src

輸入數組

dst

輸出數組,支持原地運算

a

輸出數組的最小/最大值或者輸出數組的範數

b

輸出數組的最大/最小值

norm_type

歸一化的類型,能夠有如下的取值:

CV_C - 歸一化數組的C-範數(絕對值的最大值)

CV_L1 - 歸一化數組的L1-範數(絕對值的和)

CV_L2 - 歸一化數組的(歐幾里德)L2-範數

CV_MINMAX - 數組的數值被平移或縮放到一個指定的範圍

mask

操做掩膜,用於指示函數是否僅僅對指定的元素進行操做

該函數歸一化輸入數組使它的範數或者數值範圍在必定的範圍內

當norm_type==CV_MINMAX:

dst(i,j)=(src(i,j)-min(src))*(b'-a')/(max(src)-min(src)) + a', if mask(i,j)!=0

dst(i,j)=src(i,j) otherwise

其中b'=MAX(a,b), a'=MIN(a,b);

當norm_type!=CV_MINMAX:

dst(i,j)=src(i,j)*a/cvNorm(src,0,norm_type,mask), if mask(i,j)!=0

dst(i,j)=src(i,j) otherwise

下面是一個簡單的例子: float v[3] = { 1, 2, 3 };

CvMat V = cvMat( 1, 3, CV_32F, v );

// make vector v unit-length;

// equivalent to

// for(int i=0;i<3;i++) v[i]/=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);

cvNormalize( &V, &V );

 

CrossProduct

計算兩個三維向量的叉積

void cvCrossProduct( const CvArr* src1, const CvArr* src2, CvArr* dst );

src1

第一輸入向量。

src2

第二輸入向量。

dst

輸出向量

函數 cvCrossProduct 計算兩個三維向量的差積:

dst = src1 × src2, (dst1 = src12src23 - src13src22 , dst2 = src13src21 - src11src23 , dst3 = src11src22 - src12src21).

 

ScaleAdd

計算一個數組縮放後與另外一個數組的和

void cvScaleAdd( const CvArr* src1, CvScalar scale, const CvArr* src2, CvArr* dst );

#define cvMulAddS cvScaleAdd

src1

第一輸入數組

scale

第一輸入數組的縮放因子

src2

第二輸入數組

dst

輸出數組

函數 cvScaleAdd 計算一個數組縮放後與另外一個數組的和:

dst(I)=src1(I)*scale + src2(I)

全部的數組參數必須有相同的類型和大小。

 

GEMM

通用矩陣乘法

void  cvGEMM( const CvArr* src1, const CvArr* src2, double alpha,

              const CvArr* src3, double beta, CvArr* dst, int tABC=0 );

#define cvMatMulAdd( src1, src2, src3, dst ) cvGEMM( src1, src2, 1, src3, 1, dst, 0 )

#define cvMatMul( src1, src2, dst ) cvMatMulAdd( src1, src2, 0, dst )

src1

第一輸入數組

src2

第二輸入數組

src3

第三輸入數組 (偏移量),若是沒有偏移量,能夠爲空( NULL) 。

dst

輸出數組

tABC

T操做標誌,能夠是 0 或者下面列舉的值的組合:

CV_GEMM_A_T - 轉置 src1

CV_GEMM_B_T - 轉置 src2

CV_GEMM_C_T - 轉置 src3

例如, CV_GEMM_A_T+CV_GEMM_C_T 對應

alpha*src1T*src2 + beta*src3T

函數 cvGEMM 執行通用矩陣乘法:

dst = alpha*op(src1)*op(src2) + beta*op(src3), 這裏 op(X) 是 X 或者 XT

全部的矩陣應該有相同的數據類型和協調的矩陣大小。支持實數浮點矩陣或者複數浮點矩陣。

 

Transform

對數組每個元素執行矩陣變換

void cvTransform( const CvArr* src, CvArr* dst, const CvMat* transmat, const CvMat* shiftvec=NULL );

src

輸入數組

dst

輸出數組

transmat

變換矩陣

shiftvec

可選偏移向量

函數 cvTransform 對數組 src 每個元素執行矩陣變換並將結果存儲到 dst:

dst(I)=transmat*src(I) + shiftvec

或者

dst(I)k=sumj(transmat(k,j)*src(I)j) + shiftvec(k)

N-通道數組 src 的每個元素都被視爲一個N元向量,使用一個 M×N 的變換矩陣 transmat 和偏移向量 shiftvec 把它變換到一個 M-通道的數組 dst 的一個元素中。 這裏能夠選擇將偏移向量 shiftvec 嵌入到 transmat 中。這樣的話 transmat 應該是 M×(N+1) 的矩陣,而且最右邊的一列被看做是偏移向量 。

輸入數組和輸出數組應該有相同的位深(depth)和一樣的大小或者 ROI 大小。 transmat 和 shiftvec 應該是實數浮點矩陣。

該函數能夠用來進行 ND 點集的幾何變換,任意的線性顏色空間變換,通道轉換等。

 

PerspectiveTransform

向量數組的透視變換

void cvPerspectiveTransform( const CvArr* src, CvArr* dst, const CvMat* mat );

src

輸入的三通道浮點數組

dst

輸出三通道浮點數組

mat

4 × 4 變換矩陣

函數 cvPerspectiveTransform 用下面的方式變換 src 的每個元素 (經過將其視爲二維或者三維的向量):

(x, y, z) -> (x'/w, y'/w, z'/w)

或者

(x, y) -> (x'/w, y'/w),

這裏

(x', y', z', w') = mat*(x, y, z, 1)

或者

(x', y', w') = mat*(x, y, 1)

而且 w = w' 若是 w'!=0, 不然 w = inf

 

MulTransposed

計算數組和數組的轉置的乘積

void cvMulTransposed( const CvArr* src, CvArr* dst, int order, const CvArr* delta=NULL );

src

輸入矩陣

dst

目標矩陣

order

乘法順序

delta

一個可選數組, 在乘法以前從 src 中減去該數組。

函數 cvMulTransposed 計算 src 和它的轉置的乘積。

函數求值公式:

若是 order=0

dst=(src-delta)*(src-delta)T

不然

dst=(src-delta)T*(src-delta)

 

Trace

返回矩陣的跡

CvScalar cvTrace( const CvArr* mat );

mat

輸入矩陣

函數 cvTrace 返回矩陣mat的對角線元素的和。

 

Transpose

矩陣的轉置

void cvTranspose( const CvArr* src, CvArr* dst );

#define cvT cvTranspose

src

輸入矩陣

dst

目標矩陣

函數 cvTranspose 對矩陣 src 求轉置:

dst(i,j)=src(j,i)

注意,假設是複數矩陣不會求得複數的共軛。共軛應該是獨立的:查看的 cvXorS 例子代碼。

 

Det

返回矩陣的行列式值

double cvDet( const CvArr* mat );

mat

輸入矩陣

函數 cvDet 返回方陣 mat 的行列式值。對小矩陣直接計算,對大矩陣用 高斯(GAUSSIAN)消去法。對於對稱正定(positive-determined)矩陣也能夠用 SVD 函數來求,U=V=NULL ,而後用 w 的對角線元素的乘積來計算行列式。

 

Invert

查找矩陣的逆矩陣或僞逆矩陣

double cvInvert( const CvArr* src, CvArr* dst, int method=CV_LU );

#define cvInv cvInvert

src

輸入矩陣

dst

目標矩陣

method

求逆方法:

CV_LU -最佳主元選取的高斯消除法

CV_SVD - 奇異值分解法 (SVD)

CV_SVD_SYM - 正定對稱矩陣的 SVD 方法

函數 cvInvert 對矩陣 src 求逆並將結果存儲到 dst。

若是是 LU 方法該函數返回 src 的行列式值 (src 必須是方陣)。 若是是 0, 矩陣不求逆, dst 用 0 填充。

若是 SVD 方法該函數返回 src 的條件數的倒數(最小奇異值和最大奇異值的比值) ,若是 src 全爲 0 則返回0。 若是 src 是奇異的, SVD 方法計算一個僞逆矩陣。

 

Solve

求解線性系統或者最小二乘法問題

int cvSolve( const CvArr* src1, const CvArr* src2, CvArr* dst, int method=CV_LU );

src1

輸入矩陣

src2

線性系統的右部

dst

輸出解答

method

解決方法(矩陣求逆) :

CV_LU - 最佳主元選取的高斯消除法

CV_SVD - 奇異值分解法 (SVD)

CV_SVD_SYM - 對正定對稱矩陣的 SVD 方法

函數 cvSolve 解決線性系統或者最小二乘法問題 (後者用 SVD 方法能夠解決):

 

若是使用 CV_LU 方法。 若是 src1 是非奇異的,該函數則返回 1 ,不然返回 0 ,在後一種狀況下 dst 是無效的。

 

SVD

對實數浮點矩陣進行奇異值分解

void cvSVD( CvArr* A, CvArr* W, CvArr* U=NULL, CvArr* V=NULL, int flags=0 );

A

M×N 的輸入矩陣

W

結果奇異值矩陣 (M×N 或者 N×N) 或者 向量 (N×1).

U

可選的左部正交矩陣 (M×M or M×N). 若是 CV_SVD_U_T 被指定, 應該交換上面所說的行與列的數目。

V

可選右部正交矩陣(N×N)

flags

操做標誌; 能夠是 0 或者下面的值的組合:

· CV_SVD_MODIFY_A 經過操做能夠修改矩陣 src1 。這樣處理速度會比較快。

· CV_SVD_U_T 意味着會返回轉置矩陣 U ,指定這個標誌將加快處理速度。

· CV_SVD_V_T 意味着會返回轉置矩陣 V ,指定這個標誌將加快處理速度。

函數 cvSVD 將矩陣 A 分解成一個對角線矩陣和兩個正交矩陣的乘積:

 

這裏 W 是一個奇異值的對角線矩陣,它能夠被編碼成奇異值的一維向量,U 和 V 也是同樣。 全部的奇異值都是非負的並按降序存儲。(U 和 V 也相應的存儲)。

SVD 算法在數值處理上已經很穩定,它的典型應用包括:

·       當 A 是一個方陣、對稱陣和正矩陣時精確的求解特徵值問題,例如, 當 A 時一個協方差矩陣時。在這種狀況下 W 將是一個特徵值的的向量,而且 U=V是矩陣的特徵向量(所以,當須要計算特徵向量時 U 和 V 只須要計算其中一個就能夠了) 。

·       精確的求解病態線性系統。

·       超定線性系統的最小二乘求解。上一個問題和這個問題均可以用指定 CV_SVD 的 cvSolve 方法。

·       精確計算矩陣的不一樣特徵,如秩(非零奇異值的數目), 條件數(最大奇異值和最小奇異值的比例), 行列式值(行列式的絕對值等於奇異值的乘積).上述的全部這些值都不要求計算矩陣 U 和 V 。

SVBkSb

奇異值回代算法(back substitution)

void  cvSVBkSb( const CvArr* W, const CvArr* U, const CvArr* V,

                const CvArr* B, CvArr* X, int flags );

W

奇異值矩陣或者向量

U

左正交矩陣 (多是轉置的)

V

右正交矩陣 (多是轉置的)

B

原始矩陣 A 的僞逆的乘法矩陣。這個是可選參數。若是它被省略則假定它是一個適當大小的單位矩陣(所以 x 將是 A 的僞逆的重建).。

X

目標矩陣: 奇異值回代算法的結果

flags

操做標誌, 和剛剛討論的 cvSVD 的標誌同樣。

函數 cvSVBkSb 爲被分解的矩陣 A 和矩陣 B 計算回代逆(back substitution) (參見 cvSVD 說明) :

X=V*W-1*UT*B

這裏

W-1(i,i)=1/W(i,i) 若是 W(i,i) > epsilon•sumiW(i,i),

不然:0.

epsilon 是一個依賴於矩陣數據類型的的很小的數。該函數和 cvSVD 函數被用來執行 cvInvert 和 cvSolve, 用這些函數 (svd & bksb)的緣由是初級函數(low-level) 函數能夠避免高級函數 (inv & solve) 計算中內部分配的臨時矩陣。

 

 

EigenVV

計算對稱矩陣的特徵值和特徵向量

void cvEigenVV( CvArr* mat, CvArr* evects, CvArr* evals, double eps=0 );

mat

輸入對稱方陣。在處理過程當中將被改變。

evects

特徵向量輸出矩陣, 連續按行存儲

evals

特徵值輸出矩陣,按降序存儲(固然特徵值和特徵向量的排序是同步的)。

eps

對角化的精確度 (典型地, DBL_EPSILON=≈10-15 就足夠了)。

函數 cvEigenVV 計算矩陣 A 的特徵值和特徵向量:

mat*evects(i,:)' = evals(i)*evects(i,:)' (在 MATLAB 的記法)

矩陣 A 的數據將會被這個函數修改。

目前這個函數比函數 cvSVD 要慢,精確度要低, 若是已知 A 是正定的,(例如, 它是一個協方差矩陣), 它一般被交給函數 cvSVD 來計算其特徵值和特徵向量,尤爲是在不須要計算特徵向量的狀況下

 

 

CalcCovarMatrix

計算向量集合的協方差矩陣

void cvCalcCovarMatrix( const CvArr** vects, int count, CvArr* cov_mat, CvArr* avg, int flags );

vects

輸入向量。他們必須有一樣的數據類型和大小。這個向量不必定非是一維的,他們也能夠是二維(例如,圖像)等等。

count

輸入向量的數目

cov_mat

輸出協方差矩陣,它是浮點型的方陣。

avg

輸入或者輸出數組 (依賴於標記「flags」) - 輸入向量的平均向量。

flags

操做標誌,下面值的組合:

CV_COVAR_SCRAMBLED - 輸出協方差矩陣按下面計算:

scale * [vects[0] − avg,vects[1] − avg,...]T * [vects[0] − avg,vects[1] − avg,...], 即協方差矩陣是 count×count. 這樣一個不尋常的矩陣用於一組大型向量的快速PCA方法(例如, 人臉識別的 EigenFaces 技術)。這個混雜("scrambled")矩陣的特徵值將和真正的協方差矩陣的特徵值匹配,真正的特徵向量能夠很容易的從混雜("scrambled")協方差矩陣的特徵向量中計算出來。

CV_COVAR_NORMAL - 輸出協方差矩陣被計算成:

scale * [vects[0] − avg,vects[1] − avg,...] * [vects[0] − avg,vects[1] − avg,...]T, 也就是說, cov_mat 將是一個和每個輸入向量的元素數目具備一樣線性大小的一般協方差矩陣。 CV_COVAR_SCRAMBLED 和 CV_COVAR_NORMAL 只能同時指定其中一個。

CV_COVAR_USE_AVG - 若是這個標誌被指定, 該函數將不會從輸入向量中計算 avg ,而是用過去的 avg 向量,若是 avg 已經以某種方式計算出來了這樣作是頗有用的。或者若是協方差矩陣是部分計算出來的 - 假若這樣, avg 不是輸入向量的子集的平均值,而是整個集合的平均向量。

CV_COVAR_SCALE - 若是這個標誌被指定,協方差矩陣被縮放了。 the covariation matrix is scaled.在 "normal" 模式下縮放比例是 1./count, 在 "scrambled" 模式下縮放比例是每個輸入向量的元素總和的倒數。 缺省地(若是沒有指定標誌) 協方差矩陣不被縮放 (scale=1)。

函數 cvCalcCovarMatrix 計算輸入向量的協方差矩陣和平均向量。該函數 能夠被運用到主成分分析中(PCA),以及馬氏距離(Mahalanobis distance)比較向量中等等。

  

Mahalanobis

計算兩個向量之間的馬氏距離(Mahalanobis distance)

double cvMahalanobis( const CvArr* vec1, const CvArr* vec2, CvArr* mat );

vec1

第一個一維輸入向量

vec2

第二個一維輸入向量

mat

協方差矩陣的逆矩陣

函數 cvMahalanobis 計算兩個向量之間的加權距離,其返回結果是:

協方差矩陣能夠用函數cvCalcCovarMatrix 計算出來,逆矩陣能夠用函數 cvInvert 計算出來 (CV_SVD 方法是一個比較好的選擇, 由於矩陣多是奇異的).

 

 

CalcPCA

對一個向量集作PCA變換

void cvCalcPCA( const CvArr* data, CvArr* avg,

               CvArr* eigenvalues, CvArr* eigenvectors, int flags );

data

輸入數據,每一個向量是單行向量(CV_PCA_DATA_AS_ROW)或者單列向量(CV_PCA_DATA_AS_COL).

avg

平均向量,在函數內部計算或者由調用者提供

eigenvalues

輸出的協方差矩陣的特徵值

eigenvectors

輸出的協方差矩陣的特徵向量(也就是主份量),每一個向量一行

flags

操做標誌,能夠是如下幾種方式的組合:

CV_PCA_DATA_AS_ROW - 向量以行的方式存放(也就是說任何一個向量都是連續存放的)

CV_PCA_DATA_AS_COL - 向量以列的方式存放(也就是說某一個向量成分的數值是連續存放的)

(上面兩種標誌是互相排斥的)

CV_PCA_USE_AVG - 使用預先計算好的平均值

該函數對某個向量集作PCA變換.它首先利用cvCalcCovarMatrix計算協方差矩陣而後計算協方差矩陣的特徵值與特徵向量.輸出的特徵值/特徵向量的個數小於或者等於MIN(rows(data),cols(data)).

 

ProjectPCA

把向量向某個子空間投影

void cvProjectPCA( const CvArr* data, const CvArr* avg,

                  const CvArr* eigenvectors, CvArr* result )

data

輸入數據,每一個向量能夠是單行或者單列

avg

平均向量.要麼它是單行向量那麼意味着輸入數據以行數據的形式存放,要麼就是單列向量,那麼就意味着那麼輸入向量就是以列的方式存放.

eigenvectors

特徵向量(主份量),每一個向量一行.

result

輸出的分解係數矩陣,矩陣的行數必須與輸入向量的個數相等,矩陣的列數必須小於特徵向量的行數.

該函數將輸入向量向一個正交系(eigenvectors)投影.在計算點乘以前,輸入向量要減去平均向量:

result(i,:)=(data(i,:)-avg)*eigenvectors' // for CV_PCA_DATA_AS_ROW layout.

 

BackProjectPCA

根據投影係數重構原來的向量

void cvBackProjectPCA( const CvArr* proj, const CvArr* avg,

                      const CvArr* eigenvects, CvArr* result );

proj

輸入數據,與cvProjectPCA裏面的格式一致

avg

平均向量.若是它是單行向量,那麼意味着輸出向量是以行的方式存放.不然就是單列向量,那麼輸出向量就是以列的方式存放.

eigenvectors

特徵向量(主份量),每一個向量一行.

result

輸出的重構出來的矩陣

該函數根據投影係數重構原來的向量:

result(i,:)=proj(i,:)*eigenvectors + avg // for CV_PCA_DATA_AS_ROW layout.

 

 

數學函數

 

Round, Floor, Ceil

轉換浮點數爲整數

int cvRound( double value );

int cvFloor( double value );

int cvCeil( double value );

value

輸入浮點值

函數 cvRound, cvFloor, cvCeil 用一種舍入方法將輸入浮點數轉換成整數。 cvRound 返回和參數最接近的整數值。 cvFloor 返回不大於參數的最大整數值。cvCeil 返回不小於參數的最小整數值。在某些體系結構中該函數 工做起來比標準 C 操做起來還要快。若是參數的絕對值大於 231 ,結果是不可預料的。對特殊值 (±Inf, NaN) 未進行處理。

 

Sqrt

計算平方根

float cvSqrt( float value );

value

輸入浮點值

函數 cvSqrt 計算輸入值的平方根。若是輸入的是複數, 結果將不可預料。

 

InvSqrt

計算平方根的倒數

float cvInvSqrt( float value );

value

輸入浮點值

函數 cvInvSqrt 計算輸入值的平方根的倒數,大多數狀況下它比 1./sqrt(value) 要快。 若是輸入的是 0 或者複數,結果將不可預料。特別值 (±Inf, NaN) 是不可控制的。

 

Cbrt

計算立方根

float cvCbrt( float value );

value

輸入浮點值

函數 cvCbrt 計算輸入值的立方根,大多數狀況下它比 pow(value,1./3) 要快。 另外, 負數也是可操做的。特別值 (±Inf, NaN) 是不可控制的。

 

FastArctan

計算二維向量的角度

float cvFastArctan( float y, float x );

x

二維向量的 x 座標

y

二維向量的 y 座標

函數 cvFastArctan 計算二維向量的全範圍角度角度, 變化範圍是 0°到 360°。 精確度爲 ~0.1° 。

 

IsNaN

判斷輸入是不是一個數字

int cvIsNaN( double value );

value

輸入浮點值

函數 cvIsNaN 發現輸入是一個數字則返回 1 ( IEEE754 標準 ),不然返回 0 。

 

IsInf

判斷輸入是不是無窮大

int cvIsInf( double value );

value

輸入浮點值

函數 cvIsInf 若是輸入是 ±Infinity ( IEEE754 標準 )則返回 1 ,不然返回 0 .

 

CartToPolar

計算二維向量的長度和/或者角度

void cvCartToPolar( const CvArr* x, const CvArr* y, CvArr* magnitude,

                    CvArr* angle=NULL, int angle_in_degrees=0 );

x

x 座標數組

y

y 座標數組

magnitude

存儲向量長度輸出數組, 若是不是必要的它能夠爲空(NULL)

angle

存儲角度輸出數組, 若是不是必要的它能夠爲空(NULL)。它能夠被標準化爲弧度 (0..2π) 或者度數(0..360°)

全部的數組只支持浮點類型的運算,也即x,y,magnitude,angle必須是浮點類型的數組。

angle_in_degrees

指示角度是用弧度或者度數表示的標誌,缺省模式爲弧度

函數 cvCartToPolar 計算二維向量(x(I),y(I))的長度,角度,或者二者同時計算:

magnitude(I) = sqrt(x(I)2 + y(I)2),

 

angle(I) = atan(y(I) / x(I))

角度的精確度 ≈0.1°. (0,0) 點的角度被設置爲 0.

(建議:英文文檔雖然是寫成atan( y(I)/x(I) ),可是建議和C中的表達方式統一。atan不能識別在那個象限,只能返回0-180°,atan2(x,y)才能返回0-360°的值)

 

PolarToCart

計算極座標形式的二維向量對應的直角座標

void cvPolarToCart( const CvArr* magnitude, const CvArr* angle,

                    CvArr* x, CvArr* y, int angle_in_degrees=0 );

magnitude

長度數組.若是爲空(NULL),長度被假定爲全是 1's.

angle

角度數組,弧度或者角度表示.

x

輸出 x 座標數組, 若是不須要,能夠爲空(NULL).

y

輸出 y 座標數組, 若是不須要,能夠爲空(NULL).

angle_in_degrees

指示角度是用弧度或者度數表示的標誌,缺省模式爲弧度

函數 cvPolarToCart 計算每一個向量magnitude(I)*exp(angle(I)*j), j=sqrt(-1)的 x 座標,y 座標或者二者都計算:

x(I)=magnitude(I)*cos(angle(I)),

y(I)=magnitude(I)*sin(angle(I))

 

Pow

對數組內每一個元素求冪

void cvPow( const CvArr* src, CvArr* dst, double power );

src

輸入數組

dst

輸出數組, 應該和輸入數組有相同的類型

power

冪指數

函數 cvPow 計算輸入數組的每一個元素的 p 次冪:

dst(I)=src(I)^p, 若是p是整數

不然dst(I)=abs(src(I))^p

也就是說,對於非整型的冪指數使用輸入數組元素的絕對值進行計算。然而,使用一些額外的操做,負值也能夠獲得正確的結果,象下面的例子,計算數組元素的立方根:

CvSize size = cvGetSize(src);

CvMat* mask = cvCreateMat( size.height, size.width, CV_8UC1 );

cvCmpS( src, 0, mask, CV_CMP_LT ); /* 查找負數 */

cvPow( src, dst, 1./3 );

cvSubRS( dst, cvScalarAll(0), dst, mask ); /* 輸入的負值的結果求反 */

cvReleaseMat( &mask );

對於一些冪值, 例如整數值, 0.5 和 -0.5, 優化算法被使用。

 

Exp

計算數組元素的指數冪

void cvExp( const CvArr* src, CvArr* dst );

src

輸入數組

dst

輸出數組, 它應該是 double 型的或者和輸入數組有相同的類型

函數 cvExp 計算輸入數組的每一個元素的 e 次冪:

dst(I)=exp(src(I))

最大相對偏差爲 ≈7e-6. 一般, 該函數轉換沒法輸出的值爲 0 輸出。

 

Log

計算每一個數組元素的絕對值的天然對數

void cvLog( const CvArr* src, CvArr* dst );

src

輸入數組。

dst

輸出數組,它應該是 double 型的或者和輸入數組有相同的類型。

函數 cvLog 計算輸入數組每一個元素的絕對值的天然對數:

dst(I)=log(abs(src(I))), src(I)!=0

dst(I)=C,  src(I)=0

這裏 C 是一個大負數 (≈-700 如今的實現中)。

 

SolveCubic

求解曲線函數的實根

void cvSolveCubic( const CvArr* coeffs, CvArr* roots );

coeffs

等式係數, 一個三到四個元素的數組.

roots

輸出的矩陣等式的實根。它應該具備三個元素.

函數 cvSolveCubic 求解曲線函數的實根:

coeffs[0]*x^3 + coeffs[1]*x^2 + coeffs[2]*x + coeffs[3] = 0

(若是coeffs是四元素的矢量)

或者

x^3 + coeffs[0]*x^2 + coeffs[1]*x + coeffs[2] = 0

(若是coeffs是三元素的矢量)

函數返回求解獲得的實根數目. 實根被存儲在矩陣root中, 若是隻有一個實根則用0來替代相關值.

隨機數生成 

RNG

初始化隨機數生成器狀態

CvRNG cvRNG( int64 seed=-1 );

seed

64-bit 的值用來初始化一個隨機序列

函數 cvRNG 初始化隨機數生成器並返回其狀態。指向這個狀態的指針能夠傳遞給函數 cvRandInt, cvRandReal 和 cvRandArr . 在一般的實現中使用一個 multiply-with-carry generator 。

 

RandArr

用隨機數填充數組並更新 RNG 狀態

void cvRandArr( CvRNG* rng, CvArr* arr, int dist_type, CvScalar param1, CvScalar param2 );

rng

被 cvRNG 初始化的 RNG 狀態.

arr

輸出數組

dist_type

分佈類型:

CV_RAND_UNI - 均勻分佈

CV_RAND_NORMAL - 正態分佈 或者 高斯分佈

param1

分佈的第一個參數。若是是均勻分佈它是隨機數範圍的閉下邊界。若是是正態分佈它是隨機數的平均值。

param2

分佈的第二個參數。若是是均勻分佈它是隨機數範圍的開上邊界。若是是正態分佈它是隨機數的標準差。

函數 cvRandArr 用均勻分佈的或者正態分佈的隨機數填充輸出數組。在下面的例子中該函數被用來添加一些正態分佈的浮點數到二維數組的隨機位置。

/* let's noisy_screen be the floating-point 2d array that is to be "crapped" */

CvRNG rng_state = cvRNG(0xffffffff);

int i, pointCount = 1000;

/* allocate the array of coordinates of points */

CvMat* locations = cvCreateMat( pointCount, 1, CV_32SC2 );

/* arr of random point values */

CvMat* values = cvCreateMat( pointCount, 1, CV_32FC1 );

CvSize size = cvGetSize( noisy_screen );

 

cvRandInit( &rng_state,

            0, 1, /* 如今使用虛參數之後再調整 */

            0xffffffff /*這裏使用一個肯定的種子  */,

            CV_RAND_UNI /* 指定爲均勻分佈類型 */ );

 

/* 初始化 locations */

cvRandArr( &rng_state, locations, CV_RAND_UNI, cvScalar(0,0,0,0), cvScalar(size.width,size.height,0,0) );

 

/* modify RNG to make it produce normally distributed values */

rng_state.disttype = CV_RAND_NORMAL;

cvRandSetRange( &rng_state,

                30 /* deviation */,

                100 /* average point brightness */,

                -1 /* initialize all the dimensions */ );

/* generate values */

cvRandArr( &rng_state, values, CV_RAND_NORMAL,

           cvRealScalar(100), // average intensity

           cvRealScalar(30) // deviation of the intensity

          );

 

/* set the points */

for( i = 0; i < pointCount; i++ )

{

    CvPoint pt = *(CvPoint*)cvPtr1D( locations, i, 0 );

    float value = *(float*)cvPtr1D( values, i, 0 );

    *((float*)cvPtr2D( noisy_screen, pt.y, pt.x, 0 )) += value;

}

 

/* not to forget to release the temporary arrays */

cvReleaseMat( &locations );

cvReleaseMat( &values );

 

/* RNG state does not need to be deallocated */

 

RandInt

返回 32-bit 無符號整型並更新 RNG

unsigned cvRandInt( CvRNG* rng );

rng

被 cvRNG 初始化的 RNG 狀態,被 RandSetRange (雖然, 後面這個函數對咱們正討論的函數的結果沒有什麼影響)隨意地設置。

函數 cvRandInt 返回均勻分佈的隨機 32-bit 無符號整型值並更新 RNG 狀態。它和 C 運行庫裏面的 rand() 函數十分類似,可是它產生的老是一個 32-bit 數而 rand() 返回一個 0 到 RAND_MAX (它是 2**16 或者 2**32, 依賴於操做平臺)之間的數。

該函數用來產生一個標量隨機數,例如點, patch sizes, table indices 等,用模操做能夠產生一個肯定邊界的整數,人和其餘特定的邊界縮放到 0.. 1能夠產生一個浮點數。下面是用 cvRandInt 重寫的前一個函數討論的例子:

/* the input and the task is the same as in the previous sample. */

CvRNG rng_state = cvRNG(0xffffffff);

int i, pointCount = 1000;

/* ... - no arrays are allocated here */

CvSize size = cvGetSize( noisy_screen );

/* make a buffer for normally distributed numbers to reduce call overhead */

#define bufferSize 16

float normalValueBuffer[bufferSize];

CvMat normalValueMat = cvMat( bufferSize, 1, CV_32F, normalValueBuffer );

int valuesLeft = 0;

 

for( i = 0; i < pointCount; i++ )

{

    CvPoint pt;

    /* generate random point */

    pt.x = cvRandInt( &rng_state ) % size.width;

    pt.y = cvRandInt( &rng_state ) % size.height;

 

    if( valuesLeft <= 0 )

    {  

        /* fulfill the buffer with normally distributed numbers if the buffer is empty */

        cvRandArr( &rng_state, &normalValueMat, CV_RAND_NORMAL, cvRealScalar(100), cvRealScalar(30) );

        valuesLeft = bufferSize;

    }

    ((float*)cvPtr2D( noisy_screen, pt.y, pt.x, 0 ) = normalValueBuffer[--valuesLeft];

}

 

/* there is no need to deallocate normalValueMat because we have

both the matrix header and the data on stack. It is a common and efficient

practice of working with small, fixed-size matrices */

 

RandReal

返回浮點型隨機數並更新 RNG

double cvRandReal( CvRNG* rng );

rng

被 cvRNG 初始化的 RNG 狀態

函數 cvRandReal 返回均勻分佈的隨機浮點數,範圍在 0..1 之間 (不包括 1 )。

 

離散變換

 

 

DFT

執行一維或者二維浮點數組的離散傅立葉正變換或者離散傅立葉逆變換

#define CV_DXT_FORWARD  0

#define CV_DXT_INVERSE  1

#define CV_DXT_SCALE:2

#define CV_DXT_ROWS: 4

#define CV_DXT_INV_SCALE (CV_DXT_SCALE|CV_DXT_INVERSE)

#define CV_DXT_INVERSE_SCALE CV_DXT_INV_SCALE

void cvDFT( const CvArr* src, CvArr* dst, int flags, int nonzero_rows=0);

src

輸入數組, 實數或者複數.

dst

輸出數組,和輸入數組有相同的類型和大小。

flags

變換標誌, 下面的值的組合:

CV_DXT_FORWARD - 正向 1D 或者 2D 變換. 結果不被縮放.

CV_DXT_INVERSE - 逆向 1D 或者 2D 變換. 結果不被縮放.固然 CV_DXT_FORWARD 和 CV_DXT_INVERSE 是互斥的.

CV_DXT_SCALE - 對結果進行縮放: 用數組元素數除以它. 一般, 它和 CV_DXT_INVERSE 組合在一塊兒,可使用縮寫 CV_DXT_INV_SCALE.

CV_DXT_ROWS - 輸入矩陣的每一個獨立的行進行整型或者逆向變換。這個標誌容許用戶同時變換多個向量,減小開銷(它每每比處理它本身要快好幾倍), 進行 3D 和高維的變換等等。

nonzero_rows

輸入矩陣中非0行的個數(在2維的Forward變換中),或者是輸出矩陣中感興趣的行(在反向的2維變換中)。若是這個值是負數,0,或者大於總行數的一個值,它將會被忽略。這個參數能夠用來加速2維DFT/IDFT的速度。見下面的例子。


函數 cvDFT 執行一維或者二維浮點數組的離散傅立葉正變換或者離散傅立葉逆變換:

N 元一維向量的正向傅立葉變換:

y = F(N)•x, 這裏 F(N)jk=exp(-i•2Pi•j•k/N), i=sqrt(-1)

N 元一維向量的逆向傅立葉變換:

x'= (F(N))-1•y = conj(F(N))•y

x = (1/N)•x

M×N 元二維向量的正向傅立葉變換:

Y = F(M)•X•F(N)

M×N 元二維向量的逆向傅立葉變換:

X'= conj(F(M))•Y•conj(F(N))

X = (1/(M•N))•X'

假設時實數數據 (單通道) ,從 IPL 借鑑過來的壓縮格式被用來表現一個正向傅立葉變換的結果或者逆向傅立葉變換的輸入:

Re Y0,0:  Re Y0,1:Im Y0,1:Re Y0,2: Im Y0,2  ...  Re Y0,N/2-1   Im Y0,N/2-1  Re Y0,N/2

Re Y1,0:  Re Y1,1:Im Y1,1:Re Y1,2: Im Y1,2  ...  Re Y1,N/2-1   Im Y1,N/2-1  Re Y1,N/2

Im Y1,0:  Re Y2,1:Im Y2,1:Re Y2,2: Im Y2,2  ...  Re Y2,N/2-1   Im Y2,N/2-1  Im Y2,N/2

............................................................................................

Re YM/2-1,0   Re YM-3,1   Im YM-3,1  Re YM-3,2   Im YM-3,2 ...  Re YM-3,N/2-1  Im YM-3,N/2-1 Re YM-3,N/2

Im YM/2-1,0   Re YM-2,1   Im YM-2,1  Re YM-2,2   Im YM-2,2 ...  Re YM-2,N/2-1  Im YM-2,N/2-1 Im YM-2,N/2

Re YM/2,0:Re YM-1,1   Im YM-1,1  Re YM-1,2   Im YM-1,2  ... Re YM-1,N/2-1  Im YM-1,N/2-1 Im YM-1,N/2

注意:若是 N 時偶數最後一列存在(is present), 若是 M 時偶數最後一行(is present).

若是是一維實數的變換結果就像上面矩陣的第一行的形式。利用DFT求解二維卷積

   CvMat* A = cvCreateMat( M1, N1, CV_32F );

   CvMat* B = cvCreateMat( M2, N2, A->type );

 

   // it is also possible to have only abs(M2-M1)+1×abs(N2-N1)+1

   // part of the full convolution result

   CvMat* conv = cvCreateMat( A->rows + B->rows - 1, A->cols + B->cols - 1, A->type );

 

   // initialize A and B

   ...

 

   int dft_M = cvGetOptimalDFTSize( A->rows + B->rows - 1 );

   int dft_N = cvGetOptimalDFTSize( A->cols + B->cols - 1 );

 

   CvMat* dft_A = cvCreateMat( dft_M, dft_N, A->type );

   CvMat* dft_B = cvCreateMat( dft_M, dft_N, B->type );

   CvMat tmp;

 

   // copy A to dft_A and pad dft_A with zeros

   cvGetSubRect( dft_A, &tmp, cvRect(0,0,A->cols,A->rows));

   cvCopy( A, &tmp );

   cvGetSubRect( dft_A, &tmp, cvRect(A->cols,0,dft_A->cols - A->cols,A->rows));

   cvZero( &tmp );

   // no need to pad bottom part of dft_A with zeros because of

   // use nonzero_rows parameter in cvDFT() call below

 

   cvDFT( dft_A, dft_A, CV_DXT_FORWARD, A->rows );

 

   // repeat the same with the second array

   cvGetSubRect( dft_B, &tmp, cvRect(0,0,B->cols,B->rows));

   cvCopy( B, &tmp );

   cvGetSubRect( dft_B, &tmp, cvRect(B->cols,0,dft_B->cols - B->cols,B->rows));

   cvZero( &tmp );

   // no need to pad bottom part of dft_B with zeros because of

   // use nonzero_rows parameter in cvDFT() call below

 

   cvDFT( dft_B, dft_B, CV_DXT_FORWBRD, B->rows );

 

   cvMulSpectrums( dft_A, dft_B, dft_A, 0 /* or CV_DXT_MUL_CONJ to get correlation

::::::::::: rather than convolution */ );

 

   cvDFT( dft_A, dft_A, CV_DXT_INV_SCALE, conv->rows ); // calculate only the top part

   cvGetSubRect( dft_A, &tmp, cvRect(0,0,conv->cols,conv->rows) );

 

   cvCopy( &tmp, conv );

 

GetOptimalDFTSize

對於給定的矢量尺寸返回最優DFT尺寸

int cvGetOptimalDFTSize( int size0 );

size0

矢量長度.

函數 cvGetOptimalDFTSize 返回最小值 N that is greater to equal to size0, such that DFT of a vector of size N can be computed fast. In the current implementation N=2p×3q×5r for some p, q, r.

The function returns a negative number if size0 is too large (very close to INT_MAX)

 

MulSpectrums

兩個傅立葉頻譜的每一個元素的乘法(Performs per-element multiplication of two Fourier spectrums)

void cvMulSpectrums( const CvArr* src1, const CvArr* src2, CvArr* dst, int flags );

src1

第一輸入數組

src2

第二輸入數組

dst

輸出數組,和輸入數組有相同的類型和大小。

flags

下面列舉的值的組合:

CV_DXT_ROWS - 把數組的每一行視爲一個單獨的頻譜 (參見 cvDFT 的參數討論).

CV_DXT_MUL_CONJ - 在作乘法以前取第二個輸入數組的共軛.

函數 cvMulSpectrums 執行兩個 CCS-packed 或者實數或複數傅立葉變換的結果複數矩陣的每一個元素的乘法。(performs per-element multiplication of the two CCS-packed or complex matrices that are results of real or complex Fourier transform.)

該函數和 cvDFT 能夠用來快速計算兩個數組的卷積.

 

DCT

執行一維或者二維浮點數組的離散餘弦變換或者離散反餘弦變換

#define CV_DXT_FORWARD  0

#define CV_DXT_INVERSE  1

#define CV_DXT_ROWS: 4

void cvDCT( const CvArr* src, CvArr* dst, int flags );

src

輸入數組, 1D 或者 2D 實數數組.

dst

輸出數組,和輸入數組有相同的類型和大小。

flags

變換標誌符, 下面值的組合:

CV_DXT_FORWARD - 1D 或者 2D 餘弦變換.

CV_DXT_INVERSE - 1D or 2D 反餘弦變換.

CV_DXT_ROWS - 對輸入矩陣的每一個獨立的行進行餘弦或者反餘弦變換. 這個標誌容許用戶同時進行多個向量的變換,能夠用來減小開銷(它每每比處理它本身要快好幾倍),以及 3D 和高維變換等等。

函數 cvDCT 執行一維或者二維浮點數組的離散餘弦變換或者離散反餘弦變換:

N 元一維向量的餘弦變換:

y = C(N)•x, 這裏 C(N)jk=sqrt((j==0?1:2)/N)•cos(Pi•(2k+1)•j/N)

N 元一維向量的反餘弦變換:

x = (C(N))-1•y = (C(N))T•y

M×N 元二維向量的餘弦變換:

Y = (C(M))•X•(C(N))T

M×N 元二維向量的反餘弦變換:

X = (C(M))T•Y•C(N)

 

 

內存存儲(memory storage)

CvMemStorage

Growing memory storage

typedef struct CvMemStorage

{

    struct CvMemBlock* bottom;/* first allocated block */

    struct CvMemBlock* top; /* the current memory block - top of the stack */

    struct CvMemStorage* parent; /* borrows new blocks from */

    int block_size; /* block size */

    int free_space; /* free space in the top block (in bytes) */

} CvMemStorage;

內存存儲器是一個可用來存儲諸如序列,輪廓,圖形,子劃分等動態增加數據結構的底層結構。它是由一系列以同等大小的內存塊構成,呈列表型 ---bottom 域指的是列首,top 域指的是當前指向的塊但未必是列尾.在bottom和top之間全部的塊(包括bottom, 不包括top)被徹底佔據了空間;在 top和列尾之間全部的塊(包括塊尾,不包括top)則是空的;而top塊自己則被佔據了部分空間 -- free_space 指的是top塊剩餘的空字節數。

新分配的內存緩衝區(或顯式的經過 cvMemStorageAlloc 函數分配,或隱式的經過 cvSeqPush, cvGraphAddEdge等高級函數分配)老是起始於當前塊(即top塊)的剩餘那部分,若是剩餘那部分能知足要求(夠分配的大小)。分配後,free_space 就減小了新分配的那部份內存大小,外加一些用來保存適當列型的附加大小。當top塊的剩餘空間沒法知足被分配的塊(緩衝區)大小時,top塊的下一個存儲塊被置爲當前塊(新的top塊) -- free_space 被置爲先前分配的整個塊的大小。

若是已經不存在空的存儲塊(即:top塊已經是列尾),則必須再分配一個新的塊(或從parent那繼承,見 cvCreateChildMemStorage)並將該塊加到列尾上去。因而,存儲器(memory storage)就如同棧(Stack)那樣, bottom指向棧底,(top, free_space)對指向棧頂。棧頂可經過 cvSaveMemStoragePos保存,經過 cvRestoreMemStoragePos 恢復指向, 經過 cvClearStorage 重置。

CvMemBlock

內存存儲塊結構

typedef struct CvMemBlock

{

        struct CvMemBlock* prev;

        struct CvMemBlock* next;

} CvMemBlock;

CvMemBlock 表明一個單獨的內存存儲塊結構。 內存存儲塊中的實際數據存儲在 header塊 以後(即:存在一個頭指針 head 指向的塊 header ,該塊不存儲數據),因而,內存塊的第 i 個字節能夠經過表達式 ((char*)(mem_block_ptr+1))[i] 得到。然而,一般不必直接去得到存儲結構的域。

CvMemStoragePos

內存存儲塊地址

typedef struct CvMemStoragePos

{

    CvMemBlock* top;

    int free_space;

} CvMemStoragePos;

該結構(如如下所說)保存棧頂的地址,棧頂能夠經過 cvSaveMemStoragePos 保存,也能夠經過 cvRestoreMemStoragePos 恢復。

CreateMemStorage

建立內存塊

CvMemStorage* cvCreateMemStorage( int block_size=0 );

block_size 

存儲塊的大小以字節表示。若是大小是 0 byte, 則將該塊設置成默認值 -- 當前默認大小爲64k.

函數 cvCreateMemStorage 建立一內存塊並返回指向塊首的指針。起初,存儲塊是空的。頭部(即:header)的全部域值都爲 0,除了 block_size 外.

CreateChildMemStorage

建立子內存塊

CvMemStorage* cvCreateChildMemStorage( CvMemStorage* parent );

parent 

父內存塊

函數 cvCreateChildMemStorage 建立一相似於普通內存塊的子內存塊,除了內存分配/釋放機制不一樣外。當一個子存儲塊須要一個新的塊加入時,它就試圖從parent 那獲得這樣一個塊。若是 parent 中 還未被佔據空間的那些塊中的第一個塊是可得到的,就獲取第一個塊(依此類推),再將該塊從 parent 那裏去除。若是不存在這樣的塊,則 parent 要麼分配一個,要麼從它本身 parent (即:parent 的 parent) 那借個過來。換句話說,徹底有可能造成一個鏈或更爲複雜的結構,其中的內存存儲塊互爲 child/ parent 關係(父子關係)。當子存儲結構被釋放或清除,它就把全部的塊還給各自的 parent. 在其餘方面,子存儲結構同普通存儲結構同樣。

子存儲結構在下列狀況中是很是有用的。想象一下,若是用戶須要處理存儲在某個塊中的動態數據,再將處理的結果存放在該塊中。在使用了最簡單的方法處理後,臨時數據做爲輸入和輸出數據被存放在了同一個存儲塊中,因而該存儲塊看上去就相似下面處理後的樣子: Dynamic data processing without using child storage.

結果,在存儲塊中,出現了垃圾(臨時數據)。然而,若是在開始處理數據前就先創建一個子存儲塊,將臨時數據寫入子存儲塊中並在最後釋放子存儲塊,那麼最終在源/目的存儲塊 (source / destination storage) 中就不會出現垃圾, 因而該存儲塊看上去應該是以下形式:Dynamic data processing using a child storage.

ReleaseMemStorage

釋放內存塊

void cvReleaseMemStorage( CvMemStorage** storage );

storage 

指向被釋放了的存儲塊的指針

函數 cvReleaseMemStorage 釋放全部的存儲(內存)塊 或者 將它們返回給各自的 parent(若是須要的話)。接下來再釋放 header塊(即:釋放頭指針 head 指向的塊 = free(head))並清除指向該塊的指針(即:head = NULL)。在釋放做爲 parent 的塊以前,先清除各自的 child 塊。

ClearMemStorage

清空內存存儲塊

void cvClearMemStorage( CvMemStorage* storage );

storage 

存儲存儲塊

函數 cvClearMemStorage 將存儲塊的 top 置到存儲塊的頭部(注:清空存儲塊中的存儲內容)。該函數並不釋放內存(僅清空內存)。假使該內存塊有一個父內存塊(即:存在一內存塊與其有父子關係),則函數就將全部的塊返回給其 parent.

MemStorageAlloc

在存儲塊中分配一內存緩衝區

void* cvMemStorageAlloc( CvMemStorage* storage, size_t size );

storage 

內存塊.

size 

緩衝區的大小.

函數 cvMemStorageAlloc 在存儲塊中分配一內存緩衝區。該緩衝區的大小不能超過內存塊的大小,不然就會致使運行時錯誤。緩衝區的地址被調整爲CV_STRUCT_ALIGN 字節 (當前爲 sizeof(double)).

MemStorageAllocString

在存儲塊中分配一文本字符串

typedef struct CvString

{

    int len;

    char* ptr;

}

CvString;

 

CvString cvMemStorageAllocString( CvMemStorage* storage, const char* ptr, int len=-1 );

storage 

存儲塊

ptr 

字符串

len 

字符串的長度(不計算‘\0’)。若是參數爲負數,函數就計算該字符串的長度。

函數 cvMemStorageAlloString 在存儲塊中建立了一字符串的拷貝。它返回一結構,該結構包含字符串的長度(該長度或經過用戶傳遞,或經過計算獲得)和指向被拷貝了的字符串的指針。

 

SaveMemStoragePos

保存內存塊的位置(地址)

void cvSaveMemStoragePos( const CvMemStorage* storage, CvMemStoragePos* pos );

storage 

內存塊.

pos 

內存塊頂部位置。

函數 cvSaveMemStoragePos 將存儲塊的當前位置保存到參數 pos 中。 函數 cvRestoreMemStoragePos 可進一步獲取該位置(地址)。

RestoreMemStoragePos

恢復內存存儲塊的位置

void cvRestoreMemStoragePos( CvMemStorage* storage, CvMemStoragePos* pos );

storage 

內存塊.

pos 

新的存儲塊的位置

函數 cvRestoreMemStoragePos 經過參數 pos 恢復內存塊的位置。該函數和函數 cvClearMemStorage 是釋放被佔用內存塊的惟一方法。注意:沒有什麼方法可去釋放存儲塊中被佔用的部份內存。

序列

CvSeq

可動態增加元素序列(OpenCV_1.0已發生改變,詳見cxtypes.h) Growable sequence of elements

#define CV_SEQUENCE_FIELDS() \

    int flags; /* micsellaneous flags */ \

    int header_size; /* size of sequence header */ \

    struct CvSeq* h_prev; /* previous sequence */ \

    struct CvSeq* h_next; /* next sequence */ \

    struct CvSeq* v_prev; /* 2nd previous sequence */ \

    struct CvSeq* v_next; /* 2nd next sequence */ \

    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 sequence grows (sequence granularity) */ \

    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;

結構CvSeq是全部OpenCV動態數據結構的基礎。在1.0版本中,將前六個成員剝離出來定義成一個宏. 經過不一樣尋常的宏定義簡化了帶有附加參數的結構 CvSeq 的擴展。爲了擴展 CvSeq, 用戶能夠定義一新的數據結構或在經過宏CV_SEQUENCE_FIELDS()所包括的 CvSeq 的域後在放入用戶自定義的域。

有兩種類型的序列 -- 稠密序列和稀疏序列。稠密序列都派生自 CvSeq, 它們用來表明可擴展的一維數組 -- 向量,棧,隊列,雙端隊列。數據間不存在空隙(即:連續存放)-- 若是元素從序列中間被刪除或插入新的元素到序列中(不是兩端),那麼此元素後邊的相關元素會被移動。稀疏序列都派生自 CvSet,後面會有詳細的討論。它們都是由節點所組成的序列,每個節點要麼被佔用空間要麼是空,由 flag 標誌指定。這些序列做爲無序的數據結構而被使用,如點集,圖,哈希表等。

域 header_size(結構的大小) 含有序列頭部節點的實際大小,此大小大於或等於 sizeof(CvSeq).當這個宏用在序列中時,應該等於 sizeof(CvSeq),若這個宏用在其餘結構中,如CvContour,結構的大小應該大於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 表示稀疏序列),同時包含形形色色的信息。

低 CV_SEQ_ELTYPE_BITS 位包含元素類型的 ID(標示符)。大多數處理函數並不會用到元素類型,而會用到存放在 elem_size 中的元素大小 。若是序列中包含 CvMat 中的數據,那麼元素的類型就與 CvMat 中的類型相匹配, 如:CV_32SC2 能夠被使用爲由二維空間中的點序列, CV_32FC1用爲由浮點數組成的序列等。經過宏 CV_SEQ_ELTYPE(seq_header_ptr) 來獲取序列中元素的類型。處理數字序列的函數判斷: elem.size 等同於序列元素的大小。除了與 CvMat 相兼容的類型外,還有幾個在頭 cvtypes.h 中定義的額外的類型。

Standard Types of Sequence Elements

 

    #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 /* unspecified type of sequence elements */

    #define CV_SEQ_ELTYPE_PTR            CV_USRTYPE1 /* =6 */

    #define CV_SEQ_ELTYPE_PPOINT         CV_SEQ_ELTYPE_PTR  /* &elem: pointer to element of other sequence */

    #define CV_SEQ_ELTYPE_INDEX          CV_32SC1  /* #elem: index of element of some other sequence */

    #define CV_SEQ_ELTYPE_GRAPH_EDGE     CV_SEQ_ELTYPE_GENERIC  /* &next_o, &next_d, &vtx_o, &vtx_d */

    #define CV_SEQ_ELTYPE_GRAPH_VERTEX   CV_SEQ_ELTYPE_GENERIC  /* first_edge, &(x,y) */

    #define CV_SEQ_ELTYPE_TRIAN_ATR      CV_SEQ_ELTYPE_GENERIC  /* vertex of the binary tree   */

    #define CV_SEQ_ELTYPE_CONNECTED_COMP CV_SEQ_ELTYPE_GENERIC  /* connected component  */

    #define CV_SEQ_ELTYPE_POINT3D        CV_32FC3  /* (x,y,z)  */

後面的 CV_SEQ_KIND_BITS 字節表示序列的類型:

Standard Kinds of Sequences

 

    /* generic (unspecified) kind of sequence */

    #define CV_SEQ_KIND_GENERIC     (0 << CV_SEQ_ELTYPE_BITS)

 

    /* dense sequence suntypes */

    #define CV_SEQ_KIND_CURVE       (1 << CV_SEQ_ELTYPE_BITS)

    #define CV_SEQ_KIND_BIN_TREE    (2 << CV_SEQ_ELTYPE_BITS)

 

    /* sparse sequence (or set) subtypes */

    #define CV_SEQ_KIND_GRAPH       (3 << CV_SEQ_ELTYPE_BITS)

    #define CV_SEQ_KIND_SUBDIV2D    (4 << 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 */

    char* data; /* pointer to the first element of the block */

} CvSeqBlock;

序列塊構成一個雙向的循環列表,所以指針 prev 和 next 永遠不會爲 null, 而老是指向序列中的前一個和後一個序列塊。也就是說:最後一個序列塊的 next 指向的就是序列中的第一個塊,而第一個塊的 prev 指向最後一個塊。域 start_index 和 count 有助於跟蹤序列中塊的位置。 例如,一個含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;

    int end_index;

} CvSlice;

 

inline CvSlice cvSlice( int start, int end );

#define CV_WHOLE_SEQ_END_INDEX 0x3fffffff

#define CV_WHOLE_SEQ  cvSlice(0, CV_WHOLE_SEQ_END_INDEX)

 

/* calculates the sequence slice length */

int cvSliceLength( CvSlice slice, const CvSeq* seq );

有關序列的一些操做函數將 CvSlice 做爲輸入參數,默認狀況下該參數一般被設置成整個序列(CV_WHOLE_SEQ)。start_index 和 end_index 任何一個均可以是負數或超過序列長度,start_index 是閉界,end_index 是開界。若是二者相等,那麼分割被認爲是空分割(即:不包含任何元素)。因爲序列被看做是循環結構, 因此分割能夠選擇序列中靠後的幾個元素,靠前的參數反而跟着它們,如 cvSlice(-2,3)。函數用下列方法來規範分割參數:首先, 調用 cvSliceLength 來決定分割的長度,而後, start_index 被使用相似於 cvGetSeqElem 的參數來規範(例如:負數也被容許)。實際的分割操做起始於規範化了的 start_index ,停止於 start_index + cvSliceLength()。(再次假設序列是循環結構)

若是函數並不接受分割參數,但你仍是想要處理序列的一部分,那麼可使用函數 cvSeqSlice 獲取子序列。 

CreateSeq

建立一序列

CvSeq* cvCreateSeq( 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).

函數 cvCreateSeq 建立一序列而且返回指向該序列的指針。函數在存儲塊中分配序列的頭部做爲一個連續軀體,而且設置結構的 flags域, elem_size域, header_size域 和 storage域 的值爲被傳遞過來的值,設置 delta_elems 爲默認值(可經過函數 cvSetSeqBlockSize 從新對其賦值),清空其餘的頭 部域,包括前sizeof(CvSeq) 個字節的空間。

SetSeqBlockSize

設置序列塊的大小

void cvSetSeqBlockSize( CvSeq* seq, int delta_elems );

seq 

序列

delta_elems 

知足元素所需的塊的大小

函數 cvSetSeqBlockSize 會對內存分配的粒度產生影響。當序列緩衝區中空間消耗完時,函數爲 delta_elems 個序列元素分配空間。若是新分配的空間與以前分配的空間相鄰的話,這兩個塊就合併,不然,就建立了一個新的序列快。所以,參數值越大,序列中出現碎片的可能性就越小,不過內存中更多的空間將被浪費。當序列被建立後,參數 delta_elems 大小將被設置爲 默認大小(1K).以後, 就可隨時調用該函數,並影響內存分配。 函數能夠修改被傳遞過來的參數值,以知足內存塊的大小限制。

SeqPush

添加元素到序列的尾部

char* cvSeqPush( CvSeq* seq, void* element=NULL );

seq 

element 

添加的元素

函數 cvSeqPush 在序列塊的尾部添加一元素並返回指向該元素得指針。若是輸入參數爲 null, 函數就僅僅分配一空間,留給下一個元素使用。下列代碼說明如何使用該函數去建立一空間。

The following code demonstrates how to create a new sequence using this function:

 

CvMemStorage* storage = cvCreateMemStorage(0);

CvSeq* seq = cvCreateSeq( CV_32SC1, /* sequence of integer elements */

                          sizeof(CvSeq), /* header size - no extra fields */

                          sizeof(int), /* element size */

                          storage /* the container storage */ );

int i;

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

{

    int* added = (int*)cvSeqPush( seq, &i );

    printf( "%d is added\n", *added );

}

 

...

/* release memory storage in the end */

cvReleaseMemStorage( &storage );

函數 cvSeqPush 的時間複雜度爲 O(1). 若是須要分配並使用的空間比較大,則存在一分配較快的函數(見:cvStartWriteSeq 和相關函數)

SeqPop

刪除序列尾部元素

void cvSeqPop( CvSeq* seq, void* element=NULL );

seq 

序列

element 

可選參數。若是該指針不爲空,就拷貝被刪元素到指針指向的位置

函數 cvSeqPop 從序列中刪除一元素。若是序列已經爲空,就報告一錯誤。函數時間複雜度爲 O(1).

SeqPushFront

在序列頭部添加元素

char* cvSeqPushFront( CvSeq* seq, void* element=NULL );

seq 

序列

element 

添加的元素

函數 cvSeqPushFront 相似於 cvSeqPush, 不過是在序列頭部添加元素。時間複雜度爲O(1).

SeqPopFront

刪除序列的頭部元素

void cvSeqPopFront( CvSeq* seq, void* element=NULL );

seq 

序列

element 

可選參數。若是該指針不爲空,就拷貝被珊元素到指針指向的位置。

函數 cvSeqPopFront 刪除序列的頭部元素。若是序列已經爲空,就報告一錯誤。函數時間複雜度爲 O(1).

SeqPushMulti

添加多個元素到序列尾部或頭部。

void cvSeqPushMulti( CvSeq* seq, void* elements, int count, int in_front=0 );

seq 

序列

elements 

待添加的元素

count 

添加的元素個數

in_front

標示在頭部仍是尾部添加元素

CV_BACK ( = 0) -- 在序列尾部添加元素。

CV_FRONT( != 0) -- 在序列頭部添加元素。

函數 cvSeqPushMulti 在序列頭部或尾部添加多個元素。元素按輸入數組中的順序被添加到序列中,不過它們能夠添加到不一樣的序列中

SeqPopMulti

刪除多個序列頭部或尾部的元素

void cvSeqPopMulti( CvSeq* seq, void* elements, int count, int in_front=0 );

seq 

序列

elements 

待刪除的元素

count 

刪除的元素個數

in_front

標示在頭部仍是尾部刪除元素

CV_BACK ( = 0) -- 刪除序列尾部元素。

CV_FRONT( != 0) -- 刪除序列頭部元素。

函數 cvSeqPopMulti 刪除多個序列頭部或尾部的元素。若是待刪除的元素個數超過了序列中的元素總數,則函數刪除儘量多的元素 。

SeqInsert

在序列中添加元素

char* cvSeqInsert( CvSeq* seq, int before_index, void* element=NULL );

seq 

序列

before_index 

元素插入的位置(索引)。若是插入的位置在 0(容許的參數最小值)前,則該函數等同於函數 cvSeqPushFront.若是是在 seq_total(容許的參數最大值)後,則該函數等同於 cvSeqPush.

element 

待插入的元素

函數 cvSeqInsert 移動 從被插入的位置到序列尾部元素所在的位置的全部元素,若是指針 element 不位 null, 則拷貝 element 中的元素到指定位置。函數返回指向被插入元素的指針。

SeqRemove

從序列中刪除指定的元素。

void cvSeqRemove( CvSeq* seq, int index );

seq 

目標序列

index 

被刪除元素的索引或位置。

函數 cvSeqRemove 刪除seq中指定索引(位置)的元素。若是這個索引超出序列的元素個數,會報告出錯。企圖從空序列中刪除元素,函數也將報告錯誤。函數經過移動序列中的元素來刪除被索引的元素。

ClearSeq

清空序列

void cvClearSeq( CvSeq* seq );

seq 

Sequence.

seq 

序列

函數 cvClearSeq 刪除序列中的全部元素。函數不會將內存返回到存儲器中,當新的元素添加到序列中時,可從新使用該內存。函數時間複雜度爲 O(1).

GetSeqElem

返回索引所指定的元素指針

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 表明所需元素的索引。 該宏首先覈查所需的元素是否屬於第一個塊,若是是,則返回該元素,不然,該宏就調用主函數 GetSeqElem. 若是索引爲負數的話,則老是調用函數 cvGetSeqElem。函數的時間複雜度爲 O(1), 假設塊的大小要比元素的數量要小。

SeqElemIdx

返回序列中元素的索引

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

seq 

序列

element 

指向序列中元素的指針

block 

可選參數, 若是不爲空(NULL),則存放包含該元素的塊的地址

函數 cvSeqElemIdx 返回元素的索引,若是該元素不存在這個序列中,則返回一負數。

cvSeqToArray

拷貝序列中的元素到一個連續的內存塊中

void* cvCvtSeqToArray( const CvSeq* seq, void* elements, CvSlice slice=CV_WHOLE_SEQ );

seq 

序列

elemenets 

指向目的(存放拷貝元素的)數組的指針,指針指向的空間必須足夠大。

slice 

拷貝到序列中的序列部分。

函數 cvCvtSeqToArray 拷貝整個序列或部分序列到指定的緩衝區中,並返回指向該緩衝區的指針.

MakeSeqHeaderForArray

構建序列

CvSeq* 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 

序列中元素的總數。參數值必須等於數據的大小

seq 

指向被使用做爲序列頭部的局部變量

block 

指向局部變量的指針

函數 cvMakeSeqHeaderForArray 初始化序列的頭部。序列塊由用戶分配(例如:在棧上)。該函數不拷貝數據。建立的序列只包含一個塊,和一個 NULL指針,所以能夠讀取指針,但試圖將元素添加到序列中則多數會引起錯誤。

SeqSlice

爲各個序列碎片創建頭

CvSeq* cvSeqSlice( const CvSeq* seq, CvSlice slice,

                   CvMemStorage* storage=NULL, int copy_data=0 );

seq 

序列

slice 

部分序列塊

storage 

存放新的序列和拷貝數據(若是須要)的目的存儲空間。若是爲NULL, 則函數使用包含該輸入數據的存儲空間。

copy_data 

標示是否要拷貝元素,若是 copy_data != 0, 則須要拷貝;若是 copy_data == 0, 則不需拷貝。

函數 cvSeqSlice 建立一序列,該序列表示輸入序列中特定的一部分(slice),。新序列要麼與原序列共享元素要麼擁有本身的一份拷貝。所以,若是 有人須要去 處理 該部分序列,但函數卻沒有 slice 參數, 則使用該函數去獲取該序列。.

CloneSeq

建立序列的一份拷貝

CvSeq* cvCloneSeq( const CvSeq* seq, CvMemStorage* storage=NULL );

seq 

序列

storage 

存放新序列的 header部分和拷貝數據(若是須要)的目的存儲塊。若是爲 NULL, 則函數使用包含輸入序列的存儲塊 。

函數 cvCloneSeq 建立輸入序列的一份徹底拷貝。調用函數 cvCloneSeq (seq, storage) 等同於調用 cvSeqSlice(seq, CV_WHOLE_SEQ, storage, 1).

SeqRemoveSlice

刪除序列的 slice部分

void cvSeqRemoveSlice( CvSeq* seq, CvSlice slice );

seq 

序列

slice 

序列中被移動的那部分

函數 cvSeqRemoveSlice 刪除序列中的 slice 部分

SeqInsertSlice

在序列中插入一數組

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

seq 

序列

slice 

序列中被移動的那部分

from_arr 

從中獲取元素的數組

函數 cvSeqInsertSlice 在指定位置插入來自數組from_arr中 全部元素。數組 from_arr 能夠是一個 矩陣也能夠是另一個序列。

SeqInvert

將序列中的元素進行逆序操做

void cvSeqInvert( CvSeq* seq );

seq 

序列

函數 cvSeqInvert 對序列進行逆序操做 -- 即:使第一個元素成爲最後一個,最後一個元素爲第一個。

SeqSort

使用特定的比較函數對序列中的元素進行排序

/* 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 func, void* userdata=NULL );

seq 

待排序的序列

func 

比較函數,按照元素間的大小關係返回負數,零,正數(見:上面的聲明和下面的例子) --相關函數爲 C 運行時庫中的 qsort, 後者(qsort)不使用參數userdata.

userdata 

傳遞給比較函數的用戶參數;有些狀況下,可避免全局變量的使用

函數 cvSeqSort 使用特定的標準對序列進行排序。下面是一個使用該函數的實例

/* Sort 2d points in top-to-bottom left-to-right order */

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( i = 0; i < 10; i++ )

{

    CvPoint pt;

    pt.x = rand() % 1000;

    pt.y = rand() % 1000;

    cvSeqPush( seq, &pt );

}

 

cvSeqSort( seq, cmp_func, 0 /* userdata is not used here */ );

 

/* print out the sorted sequence */

for( i = 0; i < seq->total; i++ )

{

    CvPoint* pt = (CvPoint*)cvSeqElem( seq, i );

    printf( "(%d,%d)\n", pt->x, pt->y );

}

 

cvReleaseMemStorage( &storage );

SeqSearch

查詢序列中的元素

/* 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 

輸出參數;(已查找到)元素的索引值

user_data 

傳遞到比較函數的用戶參數;在某些狀況下,有助於避免使用全局變量。

函數 cvSeqSearch 查找序列中的元素。若是序列已被排序,則使用二分查找(時間複雜度爲 O(log(N))不然使用簡單線性查找。若查找的元素不存在,函數返回 NULL 指針,而索引值設置爲序列中的元素數(若是使用的是線性查找)或 知足表達式 seq(i) > elem 的最小的 i.

 

StartAppendToSeq

將數據寫入序列中,並初始化該過程

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

seq 

指向序列的指針

writer 

writer 的狀態; 由該函數初始化

函數 cvStartAppendToSeq 初始化將數據寫入序列這個過程。經過宏 CV_WRITE_SEQ_ELEM( written_elem, writer ),寫入的元素被添加到序列尾部。注意:在寫入期間,序列的其餘操做可能會產生的錯誤的結果,甚至破懷該序列(見 cvFlushSeqWriter 的相關描述,有助於避免這些錯誤)

StartWriteSeq

建立新序列,並初始化寫入部分(writer)

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 

寫入部分 writer 的狀態; 由該函數初始化

函數 cvStartWriteSeq 是 函數 cvCreateSeq 和函數 cvStartAppendToSeq 的組合。 指向被建立的序列的指針存放在 writer->seq 中, 經過函數cvEndWriteSeq 返回(因當在最後調用)

 

EndWriteSeq

完成寫入操做

CvSeq* cvEndWriteSeq( CvSeqWriter* writer );

writer 

寫入部分 writer 的狀態

函數 cvEndWriteSeq 完成寫入操做並返回指向被寫入元素的序列的地址。同時,函數會截取最後那個不完整的序列塊,將塊的剩餘部分返回到內存中以後,序列就能夠被安全的讀和寫。

FlushSeqWriter

根據寫入狀態,刷新序列頭部

void cvFlushSeqWriter( CvSeqWriter* writer );

writer 

寫入部分的狀態

函數 cvFlushSeqWriter 用來使用戶在寫入過程當中每當須要時讀取序列元素,好比說,覈查制定的條件。函數更新序列的頭部,從而使讀取序列中的數據成爲可能。不過,寫入並無被關閉,爲的是隨時均可以將數據寫入序列。在有些算法中,常常須要刷新,考慮使用 cvSeqPush 代替該函數。

StartReadSeq

初始化序列中的讀取過程

void cvStartReadSeq( const CvSeq* seq, CvSeqReader* reader, int reverse=0 );

seq 

序列

reader 

讀取部分的狀態;由該函數初始化

reverse 

決定遍歷序列的方向。若是 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 /* alternative way, that is prefferable if sequence elements are large,

         or their size/type is unknown at compile time */

    printf("%d is read\n", *(int*)reader.ptr );

    CV_NEXT_SEQ_ELEM( seq->elem_size, reader );

#endif

}

...

 

cvReleaseStorage( &storage );

GetSeqReaderPos

返回當前的讀取器的位置

int cvGetSeqReaderPos( CvSeqReader* reader );

reader 

讀取器的狀態.

函數 cvGetSeqReaderPos 返回當前的 reader 位置 (在 0 到 reader->seq->total - 1 中)

 

SetSeqReaderPos

移動讀取器到指定的位置。

void cvSetSeqReaderPos( CvSeqReader* reader, int index, int is_relative=0 );

reader 

reader 的狀態

index 

目的位置。若是使用了 positioning mode, 則實際位置爲 index % reader->seq->total.

is_relative 

若是不位 0, 那麼索引(index) 就相對於當前的位置

函數 cvSetSeqReaderPos 將 read 的位置移動到絕對位置,或相對於當前的位置(相對位置)

 

集合

 

CvSet

Collection of nodes

typedef struct CvSetElem

{

    int flags; /* it is negative if the node is free and zero or positive otherwise */

    struct CvSetElem* next_free; /* if the node is free, the field is a

                                    pointer to next free node */

}

CvSetElem;

 

#define CV_SET_FIELDS()    \

    CV_SEQUENCE_FIELDS()   /* inherits from CvSeq */ \

    struct CvSetElem* free_elems; /* list of free nodes */

 

typedef struct CvSet

{

    CV_SET_FIELDS()

} CvSet;

在 OpenCV 的稀疏數據結構中, CvSet 是一基本結構。

從上面的聲明中可知:CvSet 繼承自 CvSeq, 並在此基礎上增長了個 free_elems 域,該域是空節點組成的列表。集合中的每個節點,不管空否,都是線性表中的一個元素。儘管對於稠密的表中的元素沒有限制,集合(派生的結構)元素必須起始於整數域,並與結構 CvSetElem 相吻合,由於這兩個域對於(由空節點組成)集合的組織是必要的。若是節點爲空,flags 爲負,next_free 指向下一個空節點。若是節點已被佔據空間,flags 爲正, flags 包含節點索引值(使用表達式 set_elem->flags & CV_SET_ELEM_IDX_MASKH 獲取), flags 的剩餘內容由用戶決定。宏 CV_IS_SET_ELEM(set_elem.ptr)用來識別特定的節點是否爲空。

起初,集合 set 同表 list 都爲空。當須要一個來自集合中的新節點時,就從表 list 中去獲取,而後表進行了更新。若是表 list 碰巧爲空,因而就分配一內存塊,塊中的全部節點與表 list 相連。結果,集合的 total 域被設置爲空節點和非空節點的和。當非空節點別釋放後,就將它加到空節點列表中。最早被釋放的節點也就是最早被佔用空間的節點

在 OpenCV 中, CvSet 用來表明圖形(CvGraph), 稀疏多維數組(CvSparseMat), 平面子劃分(planner subdivisions)等

 

CreateSet

建立空的數據集

CvSet* cvCreateSet( int set_flags, int header_size,

                    int elem_size, CvMemStorage* storage );

set_flags 

集合的類型

header_size 

頭節點的大小;應該等於 sizeof(CvSet)

elem_size 

元素的大小;不能小8

storage 

相關容器

函數 CvCreateSet 建立一具備特定頭部節點大小和元素類型的空集。並返回指向該集合的指針。

 

SetAdd

佔用集合中的一個節點

int cvSetAdd( CvSet* set_header, CvSetElem* elem=NULL, CvSetElem** inserted_elem=NULL );

set_header 

集合

elem 

可選的輸入參數,被插入的元素。若是不爲 NULL, 函數就將數據拷貝到新分配的節點。(拷貝後,清空第一個域的 MSB)

函數 cvSetAdd 分配一新的節點,將輸入數據拷貝給它(可選),而且返回指向該節點的指針和節點的索引值。索引值可經過節點的flags域的低位中得到。函數的時間複雜度爲 O(1), 不過,存在着一個函數可快速的分配內存。(見 cvSetNew)

 

SetRemove

從點集中刪除元素

void cvSetRemove( CvSet* set_header, int index );

set_header 

集合

index 

被刪元素的索引值

函數 cvSetRemove 從點集中刪除一具備特定索引值的元素。若是指定位置的節點爲空,函數將什麼都不作。函數的時間複雜度爲 O(1), 不過,存在一函數可更快速的完成該操做,該函數就是 cvSetRemoveByPtr

 

SetNew

添加元素到點集中

CvSetElem* cvSetNew( CvSet* set_header );

set_header 

集合

函數 cvSetNew 是 cvSetAdd 的變體,內聯函數。它佔用一新節點,並返回指向該節點的指針而不是索引。

 

SetRemoveByPtr

刪除指針指向的集合元素

void cvSetRemoveByPtr( CvSet* set_header, void* elem );

set_header 

集合

elem 

被刪除的元素

函數 cvSetRemoveByPtr 是一內聯函數,是函數 cvSetRemove 輕微變化而來的。該函數並不會檢查節點是否爲空 -- 用戶負責這一檢查。

 

GetSetElem

經過索引值查找相應的集合元素

CvSetElem* cvGetSetElem( const CvSet* set_header, int index );

set_header 

集合

index 

索引值

函數 cvGetSetElem 經過索引值查找相應的元素。函數返回指向該元素的指針,若是索引值無效或相應的節點爲空,則返回 0。 若函數使用 cvGetSeqElem 去查找節點,則函數支持負的索引值。

 

ClearSet

清空點集

void cvClearSet( CvSet* set_header );

set_header 

待清空的點集

函數 cvClearSet 刪除集合中的全部元素。時間複雜度爲 O(1).

 

 

 

CvGraph

有向權圖和無向權圖

#define CV_GRAPH_VERTEX_FIELDS()    \

    int flags; /* vertex flags */   \

    struct CvGraphEdge* first; /* the first incident edge */

 

typedef struct CvGraphVtx

{

    CV_GRAPH_VERTEX_FIELDS()

}

CvGraphVtx;

 

#define CV_GRAPH_EDGE_FIELDS()      \

    int flags; /* edge flags */     \

    float weight; /* edge weight */ \

    struct CvGraphEdge* next[2]; /* the next edges in the incidence lists for staring (0) */ \

                                 /* and ending (1) vertices */ \

    struct CvGraphVtx* vtx[2]; /* the starting (0) and ending (1) vertices */

 

typedef struct CvGraphEdge

{

    CV_GRAPH_EDGE_FIELDS()

}

CvGraphEdge;

 

#define  CV_GRAPH_FIELDS()                  \

    CV_SET_FIELDS() /* set of vertices */   \

    CvSet* edges;   /* set of edges */

 

typedef struct CvGraph

{

    CV_GRAPH_FIELDS()

}

CvGraph;

在 OpenCV 圖形結構中,CvGraph 是一基本結構。

圖形結構繼承自 CvSet -- 該部分描繪了普通圖的屬性和圖的頂點,也包含了一個點集做爲其成員 -- 該點集描述了圖的邊緣。利用宏(能夠簡化結構擴展和定製)使用與其它OpenCV可擴展結構同樣的方法和技巧,一樣的方法和技巧,咱們聲明瞭定點,邊和頭部結構。雖然頂點結構和邊結構沒法從CvSetElem 顯式地繼承時,但它們知足點集元素的兩個條件(在開始是有一個整數域和知足 CvSetElem 結構)。 flags 域用來標記頂點和邊是否已被佔用或者處於其餘目的,如:遍歷圖時(見:cvStartScanGraph 等),所以最好不要去直接使用它們。圖表明的就是邊的集合。存在有向和無向的區別。對於後者(無向圖),在鏈接頂點 A 到 頂點 B 的邊同鏈接頂點 B 到 頂點 A的邊是沒什麼區別的,在某一時刻,只可能存在一個,即:要麼是<A, B>要麼是<B, A>.

 

CreateGraph

建立一個空樹

CvGraph* cvCreateGraph( int graph_flags, int header_size, int vtx_size,

                        int edge_size, CvMemStorage* storage );

graph_flags 

被建立的圖的類型。一般,無向圖爲 CV_SEQ_KIND_GRAPH,有向圖爲 CV_SEQ_KIND_GRAPH | CV_GRAPH_FLAG_ORIENTED.

header_size 

頭部大小;可能小於 sizeof(CvGraph)

vtx_size 

頂點大小;常規的定點結構必須來自 CvGraphVtx (使用宏 CV_GRAPH_VERTEX_FIELDS())

edge_size 

邊的大小;常規的邊結構必須來自 CvGraphEdge (使用宏 CV_GRAPH_EDGE_FIELDS())

storage 

圖的容器

函數 cvCreateGraph 建立一空圖而且返回指向該圖的指針。

 

GraphAddVtx

插入一頂點到圖中

int cvGraphAddVtx( CvGraph* graph, const CvGraphVtx* vtx=NULL,

                   CvGraphVtx** inserted_vtx=NULL );

graph 

vtx 

可選輸入參數,用來初始化新加入的頂點(僅大小超過 sizeof(CvGraphVtx) 的用戶自定義的域纔會被拷貝)

inserted_vertex 

可選的輸出參數。若是不爲 NULL, 則傳回新加入頂點的地址

函數 cvGraphAddVtx 將一頂點加入到圖中,並返回定點的索引

 

GraphRemoveVtx

經過索引從圖中刪除一頂點

int cvGraphRemoveVtx( CvGraph* graph, int index );

graph 

vtx_idx 

被珊頂點的索引

函數 cvGraphRemoveAddVtx 從圖中刪除一頂點,連同刪除含有此頂點的邊。若是輸入的頂點不屬於該圖的話,將報告刪除出錯(不存在而沒法刪除)。返回值爲被刪除的邊數,若是頂點不屬於該圖的話,返回 -1。

 

GraphRemoveVtxByPtr

經過指針從圖中刪除一頂點

int cvGraphRemoveVtxByPtr( CvGraph* graph, CvGraphVtx* vtx );

graph 

vtx 

指向被刪除的邊的指針

函數 cvGraphRemoveVtxByPtr 從圖中刪除一頂點,連同刪除含有此頂點的邊。若是輸入的頂點不屬於該圖的話,將報告刪除出錯(不存在而沒法刪除)。返回值爲被刪除的邊數,若是頂點不屬於該圖的話,返回 -1。

 

GetGraphVtx

經過索引值查找圖的相應頂點

CvGraphVtx* cvGetGraphVtx( CvGraph* graph, int vtx_idx );

graph 

vtx_idx 

定點的索引值

函數 cvGetGraphVtx 經過索引值查找對應的頂點,並返回指向該頂點的指針,若是不存在則返回 NULL.

 

GraphVtxIdx

返回定點相應的索引值

int cvGraphVtxIdx( CvGraph* graph, CvGraphVtx* vtx );

graph 

vtx 

指向頂點的指針

函數 cvGraphVtxIdx 返回與頂點相應的索引值

 

GraphAddEdge

經過索引值在圖中加入一條邊

int cvGraphAddEdge( CvGraph* graph, int start_idx, int end_idx,

                    const CvGraphEdge* edge=NULL, CvGraphEdge** inserted_edge=NULL );

graph 

start_idx 

邊的起始頂點的索引值

end_idx 

邊的尾部頂點的索引值(對於無向圖,參數的次序可有可無,即:start_idx 和 end_idx 可互爲起始頂點和尾部頂點)

edge 

可選的輸入參數,初始化邊的數據

inserted_edge 

可選的輸出參數,包含被插入的邊的地址。

函數 cvGraphAddEdge 鏈接兩特定的頂點。若是該邊成功地加入到圖中,返回 1; 若是鏈接兩頂點的邊已經存在,返回 0; 若是頂點沒被發現(不存在)或者起始頂點和尾部頂點是同一個定點,或其餘特殊狀況,返回 -1。 若是是後者(即:返回值爲負),函數默認的報告一個錯誤。

 

GraphAddEdgeByPtr

經過指針在圖中加入一條邊

int cvGraphAddEdgeByPtr( CvGraph* graph, CvGraphVtx* start_vtx, CvGraphVtx* end_vtx,

                         const CvGraphEdge* edge=NULL, CvGraphEdge** inserted_edge=NULL );

graph 

start_vtx 

指向起始頂點的指針

end_vtx 

指向尾部頂點的指針。對於無向圖來講,頂點參數的次序可有可無。

edge 

可選的輸入參數,初始化邊的數據

inserted_edge 

可選的輸出參數,包含被插入的邊的地址。

函數 cvGraphAddEdge 鏈接兩特定的頂點。若是該邊成功地加入到圖中,返回 1; 若是鏈接兩頂點的邊已經存在,返回 0; 若是頂點沒被發現(不存在)或者起始頂點和尾部頂點是同一個定點,或其餘特殊狀況,返回 -1。 若是是後者(即:返回值爲負),函數默認的報告一個錯誤

 

GraphRemoveEdge

經過索引值從圖中刪除頂點

void cvGraphRemoveEdge( CvGraph* graph, int start_idx, int end_idx );

graph 

start_idx 

起始頂點的索引值

end_idx 

尾部頂點的索引值。對於無向圖來講,頂點參數的次序可有可無。

函數 cvGraphRemoveEdge 刪除鏈接兩特定頂點的邊。若兩頂點並無相鏈接(即:不存在由這兩個頂點鏈接的邊),函數什麼都不作。

 

GraphRemoveEdgeByPtr

經過指針從圖中刪除邊

void cvGraphRemoveEdgeByPtr( CvGraph* graph, CvGraphVtx* start_vtx, CvGraphVtx* end_vtx );

graph 

start_vtx 

指向起始頂點的指針

end_vtx 

指向尾部頂點的指針。對於無向圖來講,頂點參數的次序可有可無。

函數 cvGraphRemoveEdgeByPtr 刪除鏈接兩特定頂點的邊。若兩頂點並無相鏈接(即:不存在由這兩個頂點鏈接的邊),函數什麼都不作。

 

FindGraphEdge

經過索引值在圖中查找相應的邊

CvGraphEdge* cvFindGraphEdge( const CvGraph* graph, int start_idx, int end_idx );

#define cvGraphFindEdge cvFindGraphEdge

graph 

start_idx 

起始頂點的索引值

end_idx 

尾部頂點的索引值。對於無向圖來講,頂點參數的次序可有可無

函數 cvFindGraphEdge 查找與兩特定頂點相對應的邊,並返回指向該邊的指針。若是該邊不存在,返回 NULL.

 

FindGraphEdgeByPtr

經過指針在圖中查找相應的邊

CvGraphEdge* cvFindGraphEdgeByPtr( const CvGraph* graph, const CvGraphVtx* start_vtx,

                                   const CvGraphVtx* end_vtx );

#define cvGraphFindEdgeByPtr cvFindGraphEdgeByPtr

graph 

start_vtx 

指向起始頂點的指針

end_vtx 

指向尾部頂點的指針。對於無向圖來講,頂點參數的次序可有可無。

函數 cvFindGraphEdgeByPtr 查找與兩特定頂點相對應的邊,並返回指向該邊的指針。若是該邊不存在,返回 NULL

 

GraphEdgeIdx

返回與該邊相應的索引值

int cvGraphEdgeIdx( CvGraph* graph, CvGraphEdge* edge );

graph 

edge 

指向該邊的指針

函數 cvGraphEdgeIdx 返回與邊對應的索引值。

 

GraphVtxDegree

(經過索引值)統計與頂點相關聯的邊數

int cvGraphVtxDegree( const CvGraph* graph, int vtx_idx );

graph 

vtx_idx 

頂點對應的索引值

函數 cvGraphVtxDegree 返回與特定頂點相關聯的邊數,包括以該頂點爲起始頂點的和尾部頂點的。統計邊數,能夠適用下列代碼:

CvGraphEdge* edge = vertex->first; int count = 0;

while( edge )

{

    edge = CV_NEXT_GRAPH_EDGE( edge, vertex );

    count++;

}

宏 CV_NEXT_GRAPH_EDGE(edge, vertex) 返回依附於該頂點的下一條邊。 

 

GraphVtxDegreeByPtr

(經過指針)統計與頂點相關聯的邊數

int cvGraphVtxDegreeByPtr( const CvGraph* graph, const CvGraphVtx* vtx );

graph 

vtx 

頂點對應的指針

函數 cvGraphVtxDegreeByPtr 返回與特定頂點相關聯的邊數,包括以該頂點爲起始頂點的和尾部頂點的

 

ClearGraph

刪除圖

void cvClearGraph( CvGraph* graph );

graph

函數 cvClearGraph 刪除該圖的全部頂點和邊。時間複雜度爲 O(1).

 

CloneGraph

克隆圖

CvGraph* cvCloneGraph( const CvGraph* graph, CvMemStorage* storage );

graph 

待拷貝的圖

storage 

容器,存放拷貝

函數 cvCloneGraph 建立圖的徹底拷貝。若是頂點和邊含有指向外部變量的指針,那麼圖和它的拷貝共享這些指針。在新的圖中,頂點和邊可能存在不一樣,由於函數從新分割了頂點和邊的點集。

 

CvGraphScanner

圖的遍歷

typedef struct CvGraphScanner

{

    CvGraphVtx* vtx;       /* current graph vertex (or current edge origin) */

    CvGraphVtx* dst;       /* current graph edge destination vertex */

    CvGraphEdge* edge;     /* current edge */

 

    CvGraph* graph;        /* the graph */

    CvSeq*   stack;        /* the graph vertex stack */

    int      index;        /* the lower bound of certainly visited vertices */

    int      mask;         /* event mask */

}

CvGraphScanner;

結構 cvGraphScanner 深度遍歷整個圖。函數的相關討論以下(看:StartScanGraph)  

 

StartScanGraph

建立一結構,用來對圖進行深度遍歷

CvGraphScanner*  cvCreateGraphScanner( CvGraph* graph, CvGraphVtx* vtx=NULL,

                                       int mask=CV_GRAPH_ALL_ITEMS );

graph 

vtx 

開始遍歷的(起始)頂點。若是爲 NULL, 便利就從第一個頂點開始(指:頂點序列中,具備最小索引值的頂點)

mask

事件掩碼(event mask)表明用戶感興趣的事件(此時 函數 cvNextGraphItem 將控制返回給用戶)。這個只多是 CV_GRAPH_ALL_ITEMS (若是用戶對全部的事件都感興趣的話)或者是下列標誌的組合:

CV_GRAPH_VERTEXT -- 在第一次被訪問的頂點處停下

CV_GRAPH_TREE_EDGE -- 在 tree edge 處停下(tree edge 指鏈接最後被訪問的頂點與接下來被訪問的頂點的邊)

CV_GRAPH_BACK_EDGE -- 在 back edge 處停下(back edge 指鏈接最後被訪問的頂點與其在搜索樹中祖先的邊)

CV_GRAPH_FORWARD_EDGE -- 在 forward edge 處停下 (forward edge 指鏈接最後被訪問的頂點與其在搜索樹中後裔的邊)

CV_GRAPH_CROSS_EDGE -- 在 cross edge 處停下(cross edge 指鏈接不一樣搜索樹中或同一搜索樹中不一樣分支的邊.只有在有向圖中, 才存在着一 概念)

CV_GRAPH_ANY_EDGE -- 在 any edge 處停下(any edge 指 任何邊,包括 tree edge, back edge, forward edge, cross edge)

CV_GRAPH_NEW_TREE -- 在每個新的搜索樹開始處停下。首先遍歷從起始頂點開始能夠訪問到的頂點和邊,而後查找搜索圖中訪問不到的頂點或邊並恢復遍歷。在開始遍歷一顆新的樹時(包括第一次調用 cvNextGraphItem 時的樹),產生 CV_GRAPH_NEW_TREE 事件。

函數 cvCreateGraphScanner 建立一結構用來深度遍歷搜索樹。函數 cvNextGraphItem 要使用該初始化了的結構 -- 層層遍歷的過程。

 

NextGraphItem

逐層遍歷整個圖

int cvNextGraphItem( CvGraphScanner* scanner );

scanner 

圖的遍歷狀態。被此函數更新。

函數 cvNextGraphItem 遍歷整個圖,直到用戶感興趣的事件發生(即:調用 cvCreateGraphScanner 時, mask 對應的事件)或遍歷結束。在前面一種狀況下,函數返回 參數mask 相應的事件,當再次調用函數時,恢復遍歷)。在後一種狀況下,返回 CV_GRAPH_OVER(-1)。當 mask 相應的事件爲 CV_GRAPH_BACKTRACKING 或 CV_GRAPH_NEW_TEEE 時, 當前正在被訪問的頂點被存放在 scanner->vtx 中。若是事件與 邊edge 相關,那幺 edge 自己被存放在 scanner->edge, 該邊的起始頂點存放在 scanner->vtx 中, 尾部節點存放在 scanner->dst 中。

 

ReleaseGraphScanner

完成圖地遍歷過程

void cvReleaseGraphScanner( CvGraphScanner** scanner );

scanner 

指向遍歷器的指針.

函數 cvGraphScanner 完成圖的遍歷過程,並釋放遍歷器的狀態。

 

 

CV_TREE_NODE_FIELDS

用於樹結點類型聲明的(助手)宏

#define CV_TREE_NODE_FIELDS(node_type)                          \

    int       flags;         /* micsellaneous flags */          \

    int       header_size;   /* size of sequence header */      \

    struct    node_type* h_prev; /* previous sequence */        \

    struct    node_type* h_next; /* next sequence */            \

    struct    node_type* v_prev; /* 2nd previous sequence */    \

    struct    node_type* v_next; /* 2nd next sequence */

宏 CV_TREE_NODE_FIELDS() 用來聲明一層次性結構,例如 CvSeq -- 全部動態結構的基本類型。若是樹的節點是由該宏所聲明的,那麼就可使用(該部分的)如下函數對樹進行相關操做。

 

CvTreeNodeIterator

打開現存的存儲結構或者建立新的文件存儲結構

typedef struct CvTreeNodeIterator

{

    const void* node;

    int level;

    int max_level;

}

CvTreeNodeIterator;

結構 CvTreeNodeIterator 用來對樹進行遍歷。該樹的節點是由宏 CV_TREE_NODE_FIELDS 聲明。

 

InitTreeNodeIterator

用來初始化樹結點的迭代器

void cvInitTreeNodeIterator( CvTreeNodeIterator* tree_iterator,

                             const void* first, int max_level );

tree_iterator 

初始化了的迭代器

first 

(開始)遍歷的第一個節點

max_level 

限制對樹進行遍歷的最高層(即:第 max_level 層)(假設第一個節點所在的層爲第一層)。例如:1 指的是遍歷第一個節點所在層,2 指的是遍歷第一層和第二層

函數 cvInitTreeNodeIterator 用來初始化樹的迭代器。

 

NextTreeNode

返回當前節點,並將迭代器 iterator 移向當前節點的下一個節點

void* cvNextTreeNode( CvTreeNodeIterator* tree_iterator );

tree_iterator 

初始化了的迭代器

函數 cvNextTreeNode 返回當前節點而且更新迭代器(iterator) -- 並將 iterator 移向(當前節點)下一個節點。換句話說,函數的行爲相似於表達式 *p++ (一般的 C 指針 或 C++ 集合迭代器)。 若是沒有更多的節點(即:當前節點爲最後的節點),則函數返回值爲 NULL.

 

PrevTreeNode

返回當前節點,並將迭代器 iterator 移向當前節點的前一個節點

void* cvPrevTreeNode( CvTreeNodeIterator* tree_iterator );

tree_iterator 

初始化了的迭代器

函數 cvPrevTreeNode 返回當前節點而且更新迭代器(iterator) -- 並將 iterator 移向(當前節點的)前一個節點。換句話說,函數的行爲相似於表達式 *p-- (一般的 C 指針 或 C++ 集合迭代器)。 若是沒有更多的節點(即:當前節點爲頭節點),則函數返回值爲 NULL.

 

TreeToNodeSeq

將全部的節點指針(即:指向樹結點的指針)收集到線性表 sequence 中

CvSeq* cvTreeToNodeSeq( const void* first, int header_size, CvMemStorage* storage );

first 

初始樹結點

header_size

線性表的表頭大小,大小一般爲 sizeof(CvSeq)

函數 cvTreeToNodeSeq 將樹的節點指針挨個的存放到線性表中。存放的順序以深度爲先。

 

InsertNodeIntoTree

將新的節點插入到樹中

void cvInsertNodeIntoTree( void* node, void* parent, void* frame );

node 

待插入的節點

parent 

樹中的父節點(即:含有子節點的節點)

frame 

頂部節點。若是節點parent 等同於 節點frame, 則將節點的域 v_prev 設爲 NULL 而不是 parent.

函數 cvInsertNodeIntoTree 將另外一個節點插入到樹中。函數不分配任何內存,僅僅修改樹節點的鏈接關係。

 

RemoveNodeFromTree

從樹中刪除節點

void cvRemoveNodeFromTree( void* node, void* frame );

node 

待刪除的節點。

frame 

頂部節點。若是 node->v.prev = NULL 且 node->h.prev = NULL, 則將 frame->v.next 設爲 node->h.next

函數 cvRemoveNodeFromTree 從樹中刪除節點。它不會釋聽任何內存,僅僅修改樹中節點的鏈接關係

 

曲線與形狀

CV_RGB

建立一個色彩值.

 #define CV_RGB( r, g, b )  cvScalar( (b), (g), (r) )

 

Line

繪製鏈接兩個點的線段

void cvLine( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,

             int thickness=1, int line_type=8, int shift=0 );

img

圖像。

pt1

線段的第一個端點。

pt2

線段的第二個端點。

color

線段的顏色。

thickness

線段的粗細程度。

line_type

線段的類型。

8 (or 0) - 8-connected line(8鄰接)鏈接 線。

4 - 4-connected line(4鄰接)鏈接線。

CV_AA - antialiased 線條。

shift

座標點的小數點位數。

函數cvLine 在圖像中的點1和點2之間畫一條線段。線段被圖像或感興趣的矩形(ROI rectangle)所裁剪。對於具備整數座標的non-antialiasing 線條,使用8-鏈接或者4-鏈接Bresenham 算法。畫粗線條時結尾是圓形的。畫 antialiased 線條使用高斯濾波。要指定線段顏色,用戶可使用使用宏CV_RGB( r, g, b )。

 

Rectangle

繪製簡單、指定粗細或者帶填充的 矩形

void cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,

                  int thickness=1, int line_type=8, int shift=0 );

img

圖像.

pt1

矩形的一個頂點。

pt2

矩形對角線上的另外一個頂點

color

線條顏色 (RGB) 或亮度(灰度圖像 )(grayscale image)。

thickness

組成矩形的線條的粗細程度。取負值時(如 CV_FILLED)函數繪製填充了色彩的矩形。

line_type

線條的類型。見cvLine的描述

shift

座標點的小數點位數。

 

函數 cvRectangle 經過對角線上的兩個頂點繪製矩形。

 

Circle

繪製圓形。

void cvCircle( CvArr* img, CvPoint center, int radius, CvScalar color,

               int thickness=1, int line_type=8, int shift=0 );

img

圖像。

center

圓心座標。

radius

圓形的半徑。

color

線條的顏色。

thickness

若是是正數,表示組成圓的線條的粗細程度。不然,表示圓是否被填充。

line_type

線條的類型。見 cvLine 的描述

shift

圓心座標點和半徑值的小數點位數。

函數cvCircle繪製或填充一個給定圓心和半徑的圓。圓被感興趣矩形所裁剪。若指定圓的顏色,可使用宏 CV_RGB ( r, g, b )。

 

Ellipse

繪製橢圓圓弧和橢圓扇形。

void cvEllipse( CvArr* img, CvPoint center, CvSize axes, double angle,

                double start_angle, double end_angle, CvScalar color,

                int thickness=1, int line_type=8, int shift=0 );

img

圖像。

center

橢圓圓心座標。

axes

軸的長度。

angle

偏轉的角度。

start_angle

圓弧起始角的角度。.

end_angle

圓弧終結角的角度。

color

線條的顏色。

thickness

線條的粗細程度。

line_type

線條的類型,見CVLINE的描述。

shift

圓心座標點和數軸的精度。

函數cvEllipse用來繪製或者填充一個簡單的橢圓弧或橢圓扇形。圓弧被ROI矩形所忽略。反走樣弧線和粗弧線使用線性分段近似值。全部的角都是以角度的形式給定的。下面的圖片將解釋這些參數的含義。

Parameters of Elliptic Arc

EllipseBox

使用一種簡單的方式來繪製橢圓圓弧和橢圓扇形。

void cvEllipseBox( CvArr* img, CvBox2D box, CvScalar color,

                   int thickness=1, int line_type=8, int shift=0 );

img

圖像。

box

繪製橢圓圓弧所須要的外界矩形.

thickness

分界線線條的粗細程度。

line_type

分界線線條的類型,見CVLINE的描述。

shift

橢圓框頂點座標的精度。

The function cvEllipseBox draws a simple or thick ellipse outline, or fills an ellipse. The functions provides a convenient way to draw an ellipse approximating some shape; that is what cvCamShift and cvFitEllipse do. The ellipse drawn is clipped by ROI rectangle. A piecewise-linear approximation is used for antialiased arcs and thick arcs.

 

FillPoly

填充多邊形內部

void cvFillPoly( CvArr* img, CvPoint** pts, int* npts, int contours,

                 CvScalar color, int line_type=8, int shift=0 );

img

圖像。

pts

指向多邊形的數組指針。

npts

多邊形的頂點個數的數組。

contours

組成填充區域的線段的數量。

color

多邊形的顏色。

line_type

組成多邊形的線條的類型。

shift

頂點座標的小數點位數。

函數cvFillPoly用於一個單獨被多邊形輪廓所限定的區域內進行填充。函數能夠填充複雜的區域,例如,有漏洞的區域和有交叉點的區域等等。

 

FillConvexPoly

填充凸多邊形

void cvFillConvexPoly( CvArr* img, CvPoint* pts, int npts,

                       CvScalar color, int line_type=8, int shift=0 );

img

圖像。

pts

指向單個多邊形的指針數組。

npts

多邊形的頂點個數。

color

多邊形的顏色。

line_type

組成多邊形的線條的類型。參見cvLine

shift

頂點座標的小數點位數。

 

函數cvFillConvexPoly填充凸多邊形內部。這個函數比函數cvFillPoly 更快。它除了能夠填充凸多邊形區域還能夠填充任何的單調多邊形。例如:一個被水平線(掃描線)至多兩次截斷的多邊形。

 

PolyLine

繪製簡單線段或折線。

void cvPolyLine( CvArr* img, CvPoint** pts, int* npts, int contours, int is_closed,

                 CvScalar color, int thickness=1, int line_type=8, int shift=0 );

img

圖像。

pts

折線的頂點指針數組。

npts

折線的定點個數數組。也能夠認爲是pts指針數組的大小

contours

折線的線段數量。

is_closed

指出多邊形是否封閉。若是封閉,函數將起始點和結束點連線。

color

折線的顏色。

thickness

線條的粗細程度。

line_type

線段的類型。參見cvLine。

shift

頂點的小數點位數。

函數cvPolyLine 繪製一個簡單直線或折線。

 

文本

 

InitFont

初始化字體結構體。

void cvInitFont( CvFont* font, int font_face, double hscale,

                 double vscale, double shear=0,

                 int thickness=1, int line_type=8 );

font

被初始化的字體結構體。

font_face

字體名稱標識符。只是Hershey 字體集( http://sources.isc.org/utils/misc/hershey-font.txt )的一個子集獲得支持。

CV_FONT_HERSHEY_SIMPLEX - 正常大小無襯線字體。

CV_FONT_HERSHEY_PLAIN - 小號無襯線字體。

CV_FONT_HERSHEY_DUPLEX - 正常大小無襯線字體。( 比CV_FONT_HERSHEY_SIMPLEX更復雜)

CV_FONT_HERSHEY_COMPLEX - 正常大小有襯線字體。

CV_FONT_HERSHEY_TRIPLEX - 正常大小有襯線字體 ( 比CV_FONT_HERSHEY_COMPLEX更復雜)

CV_FONT_HERSHEY_COMPLEX_SMALL - CV_FONT_HERSHEY_COMPLEX 的小譯本。

CV_FONT_HERSHEY_SCRIPT_SIMPLEX - 手寫風格字體。

CV_FONT_HERSHEY_SCRIPT_COMPLEX - 比CV_FONT_HERSHEY_SCRIPT_SIMPLEX更復雜。

這個參數可以由一個值和可選擇的CV_FONT_ITALIC字體標記合成,就是斜體字。

hscale

字體寬度。若是等於1.0f,字符的寬度是最初的字體寬度。若是等於0.5f,字符的寬度是最初的字體寬度的一半。

vscale

字體高度。若是等於1.0f,字符的高度是最初的字體高度。若是等於0.5f,字符的高度是最初的字體高度的一半。

shear

字體的斜度。當值爲0時 ,字符不傾斜;當值爲1.0f時,字體傾斜≈45度,等等。厚度讓字母着重顯示。函數cvLine用於繪製字母。

thickness

字體筆劃的粗細程度。

line_type

字體筆劃的類型,參見cvLine。

函數cvInitFont初始化字體結構體,字體結構體能夠被傳遞到文字顯示函數中。

 

PutText

在圖像中顯示文本字符串。

void cvPutText( CvArr* img, const char* text, CvPoint org, const CvFont* font, CvScalar color );

img

輸入圖像。

text

要顯示的字符串。

org

第一個字符左下角的座標。

font

字體結構體。

color

文本的字體顏色。

函數cvPutText將具備指定字體的和指定顏色的文本加載到圖像中。加載到圖像中的文本被感興趣的矩形框(ROI rectangle)剪切。不屬於指定字體庫的字符用矩形字符替代顯示。 

 

GetTextSize

得到字符串的寬度和高度。

void cvGetTextSize( const char* text_string, const CvFont* font, CvSize* text_size, int* baseline );

font

字體結構體

text_string

輸入字符串。

text_size

合成字符串的字符的大小。文本的高度不包括基線如下的部分。

baseline

相對於文字最底部點的基線的Y座標。

函數cvGetTextSize是用於在指定字體時計算字符串的綁定區域(binding rectangle)。

 

點集和輪廓

 

DrawContours

在圖像中繪製外部和內部的輪廓。

void cvDrawContours( CvArr *img, CvSeq* contour,

                     CvScalar external_color, CvScalar hole_color,

                     int max_level, int thickness=1,

                     int line_type=8, CvPoint offset=cvPoint(0,0) );

img

用以繪製輪廓的圖像。和其餘繪圖函數同樣,邊界圖像被感興趣區域(ROI)所剪切。

contour

指針指向第一個輪廓。

external_color

外層輪廓的顏色。

hole_color

內層輪廓的顏色。

max_level

繪製輪廓的最大等級。若是等級爲0,繪製單獨的輪廓。若是爲1,繪製輪廓及在其後的相同的級別下輪廓。若是值爲2,全部的輪廓。若是等級爲2,繪製全部同級輪廓及全部低一級輪廓,諸此種種。若是值爲負數,函數不繪製同級輪廓,但會升序繪製直到級別爲abs(max_level)-1的子輪廓。

thickness

繪製輪廓時所使用的線條的粗細度。若是值爲負(e.g. =CV_FILLED),繪製內層輪廓。

line_type

線條的類型。參考cvLine.

offset

按照給出的偏移量移動每個輪廓點座標.當輪廓是從某些感興趣區域(ROI)中提取的而後須要在運算中考慮ROI偏移量時,將會用到這個參數。

當thickness>=0,函數cvDrawContours在圖像中繪製輪廓,或者當thickness<0時,填充輪廓所限制的區域。

#include "cv.h"

#include "highgui.h"

 

int main( int argc, char** argv )

{

    IplImage* src;

    // 第一條命令行參數肯定了圖像的文件名。

    if( argc == 2 && (src=cvLoadImage(argv[1], 0))!= 0)

    {

        IplImage* dst = cvCreateImage( cvGetSize(src), 8, 3 );

        CvMemStorage* storage = cvCreateMemStorage(0);

        CvSeq* contour = 0;

 

        cvThreshold( src, src, 1, 255, CV_THRESH_BINARY );

        cvNamedWindow( "Source", 1 );

        cvShowImage( "Source", src );

 

        cvFindContours( src, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

        cvZero( dst );

 

        for( ; contour != 0; contour = contour->h_next )

        {

            CvScalar color = CV_RGB( rand()&255, rand()&255, rand()&255 );

            /* 用1替代 CV_FILLED  所指示的輪廓外形 */

            cvDrawContours( dst, contour, color, color, -1, CV_FILLED, 8 );

        }

 

        cvNamedWindow( "Components", 1 );

        cvShowImage( "Components", dst );

        cvWaitKey(0);

    }

}

在樣本中用1替代 CV_FILLED 以指示的獲得外形。

(注意:在cvFindContours中參數爲CV_CHAIN_CODE時,cvDrawContours用CV_FILLED時不會畫出任何圖形)

 

InitLineIterator

初始化直線迭代器

int cvInitLineIterator( const CvArr* image, CvPoint pt1, CvPoint pt2,

                        CvLineIterator* line_iterator, int connectivity=8,

                        int left_to_right=0 );

img

用以獲取直線的圖像。

pt1

線段的第一個端點。

pt2

線段的第二個端點。

line_iterator

指向直線迭代狀態結構體的指針。

connectivity

直線的鄰接方式,4鄰接或者8鄰接。

left_to_right

標誌值,指出掃描直線是從pt1和pt2外面最左邊的點掃描到最右邊的點(left_to_right≠0),仍是按照指定的順序,從pt1到pt2(left_to_right=0)。

函數cvInitLineIterator初始化直線迭代器並返回兩個端點間點的數目。兩個端點都必須在圖像內部。在迭代器初始化之後,全部的在鏈接兩個終點的柵欄線上的點,能夠經過訪問CV_NEXT_LINE_POINT點的方式得到。在線上的這些點使用4-鄰接或者8-鄰接的Bresenham算法計算獲得。

例:使用直線迭代來計算沿着彩色線上的點的像素值。

CvScalar sum_line_pixels( IplImage* image, CvPoint pt1, CvPoint pt2 )

    {

        CvLineIterator iterator;

        int blue_sum = 0, green_sum = 0, red_sum = 0;

        int count = cvInitLineIterator( image, pt1, pt2, &iterator, 8, 0 );

 

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

            blue_sum += iterator.ptr[0];

            green_sum += iterator.ptr[1];

            red_sum += iterator.ptr[2];

            CV_NEXT_LINE_POINT(iterator);

 

            /* print the pixel coordinates: demonstrates how to calculate the coordinates */

            {

            int offset, x, y;

            /* assume that ROI is not set, otherwise need to take it into account. */

            offset = iterator.ptr - (uchar*)(image->imageData);

            y = offset/image->widthStep;

            x = (offset - y*image->widthStep)/(3*sizeof(uchar) /* size of pixel */);

            printf("(%d,%d)\n", x, y );

            }

        }

        return cvScalar( blue_sum, green_sum, red_sum );

    }

 

 

ClipLine

剪切圖像矩形區域內部的直線。

int cvClipLine( CvSize img_size, CvPoint* pt1, CvPoint* pt2 );

img_size

圖像的大小。

pt1

線段的第一個端點,會被函數修改。

pt2

線段的第二個端點,會被函數修改。

函數cvClipLine計算線段徹底在圖像中的一部分。若是線段徹底在圖像中,返回0,不然返回1。

 

Ellipse2Poly

用折線逼近橢圓弧

int cvEllipse2Poly( CvPoint center, CvSize axes,

                    int angle, int arc_start,

                    int arc_end, CvPoint* pts, int delta );

center

弧線的中心。

axes

弧線的Half-sizes。參見下圖。

angle

橢圓的旋轉角度(Rotation angle),參見下圖。

start_angle

橢圓的Starting angle,參見下圖。

end_angle

橢圓的Ending angle,參見下圖。

pts

座標點矩陣數組,由本函數填充。

delta

與下一條折線定點的夾角,近似精度。故,獲得的點數最大爲ceil((end_angle - start_angle)/delta) + 1。

函數cvEllipse2Poly計算給定的橢圓弧的逼近折線的頂點,被cvEllipse使用。

 

文件存儲

 

CvFileStorage

文件存儲結構

typedef struct CvFileStorage

{

    ...       // hidden fields

} CvFileStorage;

構造函數 CvFileStorage 是將磁盤上存儲的文件關聯起來的「黑匣子」 。在下列函數描述中利用CvFileStorage 做爲輸入,容許存儲或載入各類格式數據組成的層次集合,這些數據由標量值(scalar ),或者CXCore 對象(例如 矩陣,序列,圖表 ) 和用戶自定義對象。

CXCore 能將數據讀入或寫入 XML (http://www.w3c.org/XML) or YAML (http://www.yaml.org) 格式. 下面這個例子是利用CXCore函數將3×3單位浮點矩陣存入XML 和 YAML文檔。

XML:

<?xml version="1.0">

<opencv_storage>

<A type_id="opencv-matrix">

  <rows>3</rows>

  <cols>3</cols>

  <dt>f</dt>

  <data>1. 0. 0. 0. 1. 0. 0. 0. 1.</data>

</A>

</opencv_storage>

YAML:

%YAML:1.0

A: !!opencv-matrix

  rows: 3

  cols: 3

  dt: f

  data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1.]

從例子中能夠看到, XML是用嵌套標籤來表現層次,而 YAML用縮排來表現(相似於Python語言) 。

相同的 CXCore 函數也可以在這兩種格式下讀寫數據,特殊的格式決定了文件的擴展名, .xml 是 XML 的擴展名, .yml 或 .yaml 是 YAML的擴展名。

 

CvFileNode

文件存儲器節點

/* 文件節點類型 */

#define CV_NODE_NONE        0

#define CV_NODE_INT         1

#define CV_NODE_INTEGER     CV_NODE_INT

#define CV_NODE_REAL        2

#define CV_NODE_FLOAT       CV_NODE_REAL

#define CV_NODE_STR         3

#define CV_NODE_STRING      CV_NODE_STR

#define CV_NODE_REF         4 /* not used */

#define CV_NODE_SEQ         5

#define CV_NODE_MAP         6

#define CV_NODE_TYPE_MASK   7

 

/* 可選標記 */

#define CV_NODE_USER        16

#define CV_NODE_EMPTY       32

#define CV_NODE_NAMED       64

 

#define CV_NODE_TYPE(tag)  ((tag) & CV_NODE_TYPE_MASK)

 

#define CV_NODE_IS_INT(tag)        (CV_NODE_TYPE(tag) == CV_NODE_INT)

#define CV_NODE_IS_REAL(tag)       (CV_NODE_TYPE(tag) == CV_NODE_REAL)

#define CV_NODE_IS_STRING(tag)     (CV_NODE_TYPE(tag) == CV_NODE_STRING)

#define CV_NODE_IS_SEQ(tag)        (CV_NODE_TYPE(tag) == CV_NODE_SEQ)

#define CV_NODE_IS_MAP(tag)        (CV_NODE_TYPE(tag) == CV_NODE_MAP)

#define CV_NODE_IS_COLLECTION(tag) (CV_NODE_TYPE(tag) >= CV_NODE_SEQ)

#define CV_NODE_IS_FLOW(tag)       (((tag) & CV_NODE_FLOW) != 0)

#define CV_NODE_IS_EMPTY(tag)      (((tag) & CV_NODE_EMPTY) != 0)

#define CV_NODE_IS_USER(tag)       (((tag) & CV_NODE_USER) != 0)

#define CV_NODE_HAS_NAME(tag)      (((tag) & CV_NODE_NAMED) != 0)

 

#define CV_NODE_SEQ_SIMPLE 256

#define CV_NODE_SEQ_IS_SIMPLE(seq) (((seq)->flags & CV_NODE_SEQ_SIMPLE) != 0)

 

typedef struct CvString

{

    int len;

    char* ptr;

}

CvString;

 

/*全部已讀存儲在文件元素的關鍵字被存儲在hash表中,這樣能夠加速查找操做 */

typedef struct CvStringHashNode

{

    unsigned hashval;

    CvString str;

    struct CvStringHashNode* next;

}

CvStringHashNode;

 

/* 文件存儲器的基本元素是-標量或集合*/

typedef struct CvFileNode

{

    int tag;

    struct CvTypeInfo* info; /* 類型信息(只能用於用戶自定義對象,對於其它對象它爲0) */

    union

    {

        double f; /* 浮點數*/

        int i;    /* 整形數 */

        CvString str; /* 字符文本 */

        CvSeq* seq; /* 序列 (文件節點的有序集合) */

        struct CvMap* map; /*圖表 (指定的文件節點的集合 ) */

    } data;

}

CvFileNode;

這個構造函數只是用於從新找到文件存儲器上的數據(例如 ,從文件中下載數據)。 當數據已經寫入文件時,按順序寫入,只用最小的緩衝完成,此時沒有數據存放在文件存儲器。

相反,當從文件中讀數據時,全部文件在內存中像樹同樣被解析和描繪。樹的每個節點被CvFileNode表現出來。文件節點N的類型可以經過CV_NODE_TYPE(N->tag) 被從新找到。一些節點(葉結點)做爲變量:字符串文本,整數,浮點數。其它的文件節點是集合文件節點,有兩個類型集合:序列和圖表 (咱們這裏使用 YAML 符號,不管用哪一種方法,對於XML符號流也是一樣有效)。序列(不要與CvSeq混淆) 是由有序的非指定文件節點(注:沒有關鍵字)構成的,圖表是由無序的指定文件節點(注:有關鍵字)構成的。於是 ,序列的數據是經過索引(cvGetSepElem)來存取,圖形的數據是經過名字(cvGetFileNodeByName)來存取 下表描述不一樣類型的節點:

Type

CV_NODE_TYPE(node->tag)

Value

Integer

CV_NODE_INT

node->data.i

Floating-point

CV_NODE_REAL

node->data.f

Text string

CV_NODE_STR

node->data.str.ptr

Sequence

CV_NODE_SEQ

node->data.seq

Map

CV_NODE_MAP

node->data.map*

這裏不須要直接存取圖表內容(順便說一下CvMap 是一個隱藏的構造函數)。圖形中的數據能夠用cvGetFileNodeByName函數獲得,函數返回指向圖表文件節點的指針。

一個用戶對象是一個標準的類型實例,例如CvMat, CvSeq等,或者任何一個已註冊的類型使用cvRegisterTypeInfo。這樣的對象最初在文件中表現爲一種層級關係,(像表現XML 和 YAM示例文件同樣) 。在文件存儲器打開並分析以後。當用戶調用cvRead或cvReadByName函數時 那麼對象將請求被解析 (按照原來的存儲方式)。

 

CvAttrList

屬性列表

typedef struct CvAttrList

{

    const char** attr; /* NULL-指向數組對(attribute_name,attribute_value) 的空指針 */

    struct CvAttrList* next; /* 指向下一個屬性塊的指針 */

}

CvAttrList;

 

/* 初始化構造函數CvAttrList */

inline CvAttrList cvAttrList( const char** attr=NULL, CvAttrList* next=NULL );

 

/* 返回值爲屬性值,找不到適合的屬性則返回值爲0(NULL)*/

const char* cvAttrValue( const CvAttrList* attr, const char* attr_name );

在當前版本的屬性列表用來傳遞額外的參數,在使用cvWrite寫入自定義數據對象時。除了對象類型說明(type_id 屬性)之外,它不支持 XML 在標籤內的屬性(注:例如<A name="test"></A>不支持)。

 

OpenFileStorage

打開文件存儲器讀/寫數據。

CvFileStorage* cvOpenFileStorage( const char* filename, CvMemStorage* memstorage, int flags );

filename

內存中的相關文件的文件名。

memstorage

內存中一般存儲臨時數據和動態結構,例如 CvSeq 和 CvGraph。若是memstorage 爲空,將創建和使用一個暫存器。

flags

讀/寫選擇器。

CV_STORAGE_READ - 內存處於讀狀態。

CV_STORAGE_WRITE - 內存處於寫狀態。

函數cvOpenFileStorage打開文件存儲器讀寫數據,以後創建文件或繼續使用現有的文件。文件擴展名決定讀文件的類型 : .xml 是 XML的擴展名, .yml 或 .yaml 是 YAML的擴展名。該函數的返回指針指向CvFileStorage結構。

 

ReleaseFileStorage

釋放文件存儲單元

void  cvReleaseFileStorage( CvFileStorage** fs );

fs

雙指針指向被關閉的文件存儲器。

函數cvReleaseFileStorage 關閉一個相關的文件存儲器並釋放全部的臨時內存。只有在內存的I/O操做完成後才能關閉文件存儲器。

 

寫數據

 

StartWriteStruct

向文件存儲器中寫數據

void  cvStartWriteStruct( CvFileStorage* fs, const char* name,

                          int struct_flags, const char* type_name=NULL,

                          CvAttrList attributes=cvAttrList());

fs

初始化文件存儲器。

name

被寫入的數據結構的名稱。在存儲器被讀取時能夠經過名稱訪問數據結構。

struct_flags

有下列兩個值:

CV_NODE_SEQ - 被寫入的數據結構爲序列結構。這樣的數據沒有名稱。

CV_NODE_MAP - 被寫入的數據結構爲圖表結構。這樣的數據含有名稱。

這兩個標誌符必須被指定一個

CV_NODE_FLOW - 這個可選擇標識符只能做用於YAML流。被寫入的數據結構被看作一個數據流(不是數據塊),它更加緊湊,當結構或數組裏的數據是標量時,推薦用這個標誌。

type_name

可選參數 - 對象類型名稱。若是是XML用打開標識符type_id 屬性寫入。若是是YAML 用冒號後面的數據結構名寫入,:: 基本上它是伴隨用戶對象出現的。當讀存儲器時,編碼類型名一般決定對象類型(見Cvtypeinfo和cvfindtypeinfo) 。

attributes

這個參數當前版本沒有使用。

函數 cvStartWriteStruct 開始寫複合的數據結構(數據集合)包括序列或圖表, 在結構體中全部的字段(能夠是標量和新的結構)被寫入後, 須要調用 cvEndWriteStruct . 該函數可以合併一些對象或寫入一些用戶對象(參考 CvTypeInfo )。

 

EndWriteStruct

結束數據結構的寫操做

void  cvEndWriteStruct( CvFileStorage* fs );

fs

初始化文件存儲器。

函數cvEndWriteStruct 結束普通的寫數據操做。

 

WriteInt

寫入一個整型值

void  cvWriteInt( CvFileStorage* fs, const char* name, int value );

fs

初始的文件存儲器。

name

寫入值的名稱。若是母結構是一個序列,把name的值置爲NULL。

value

寫入的整型值。

函數 cvWriteInt 將一個單獨的整型值(有符號的或無符號的)寫入文件存儲器。

 

WriteReal

寫入一個浮點數

void  cvWriteReal( CvFileStorage* fs, const char* name, double value );

fs

文件存儲器。

name

寫入值的名稱。若是父結構是一個序列,則name的值應爲NULL。

value

寫入的浮點數。

函數 cvWriteReal 將一個單精度浮點數(有符號的或無符號的)寫入文件存儲器。一些特殊的值以特殊的編碼表示:

    NaN     表示不是數字

    +.Inf   表示正無窮

    -.Inf   表示負無窮

下面的實例展現 怎樣使用底層寫函數存儲自定義數據結構。

void write_termcriteria( CvFileStorage* fs, const char* struct_name,

                         CvTermCriteria* termcrit )

{

    cvStartWriteStruct( fs, struct_name, CV_NODE_MAP, NULL, cvAttrList(0,0));

    cvWriteComment( fs, "termination criteria", 1 );

    if( termcrit->type & CV_TERMCRIT_ITER )

        cvWriteInteger( fs, "max_iterations", termcrit->max_iter );

    if( termcrit->type & CV_TERMCRIT_EPS )

        cvWriteReal( fs, "accuracy", termcrit->epsilon );

    cvEndWriteStruct( fs );

}

 

WriteString

寫入文本字符串

void cvWriteString( CvFileStorage* fs, const char* name,

相關文章
相關標籤/搜索