opencv学习一

opencv学习应该按照opencv的模块化设计进行学习。

基本也就分这么几块:

core——定义了基本数据结构,包括最重要的Mat和一些其他的模块

imgproc——该模块包括了线性和非线性的图像滤波,图像的几何变换,颜色空间转换,直方图处理等等

video——该模块包括运动估计,背景分离,对象跟踪

calib3d——基本的多视角几何算法,单个立体摄像头标定,物体姿态估计,立体相似性算法,3D信息的重建

features2d——显著特征检测,描述,特征匹配

objdetect——物体检测和预定义好的分类器实例(比如人脸,眼睛,面部,人,车辆等等)

highgui——视频捕捉、图像和视频的编码解码、图形交互界面的接口

gpu——利用GPU对OpenCV模块进行加速算法

ml——机器学习模块(SVM,决策树,Boosting等等)

flann——Fast Library for Approximate Nearest Neighbors(FLANN)算法库

legacy——一些已经废弃的代码库,保留下来作为向下兼容

还有一些其他的模块,比如FLANN算法库、Google测试包、Python bingdings等等。

================================================================================================================================

core 模块.核心功能

1、Mat - 基本图像容器

Mat 是一个类,由两个数据部分组成:矩阵头(包含矩阵尺寸,存储方法,存储地址等信息)和一个指向存储所有像素值的矩阵(根据所选存储方法的不同矩阵可以是不同的维数)的指针。矩阵头的尺寸是常数值,但矩阵本身的尺寸会依图像的不同而不同,通常比矩阵头的尺寸大数个数量级。因此,当在程序中传递图像并创建拷贝时,大的开销是由矩阵造成的,而不是信息头。OpenCV是一个图像处理库,囊括了大量的图像处理函数,为了解决问题通常要使用库中的多个函数,因此在函数中传递图像是家常便饭。同时不要忘了我们正在讨论的是计算量很大的图像处理算法,因此,除非万不得已,我们不应该拷贝 大 的图像,因为这会降低程序速度。

经常会碰到IplImage结构,看一下相关问题

  由于OpenCV主要针对的是计算机视觉方面的处理,因此在函数库中,最重要的结构体是IplImage结构。IplImage结构来源于Intel的另外一个函数库IntelImage Processing Library(IPL),该函数库主要是针对图像处理。IplImage结构具体定义如下:

typedef struct_IplImage

{

int nSize;                                   /*IplImage结构的大小*/

int ID;                                      /*图像头的版本*//* 版本 (=0)*/

int nChannels;                            /*通道数,据不同颜色类型的位图可取1、3、4*//*这里是指:每个位图像素是由几个点组成的,如,最经典的是24位位图,每个像素有RGB三个点组成,每个点是0~255(就是8位一个无符号字节,就是一个depth)*//*取值4,表示32位位图,有Alpha值,既位图透明度*/

intalphaChannel;                       /*Alpha通道数,没有取0,有则取4*/

int depth;                                   /*每个通道的位数,可取1、8、16、32*//*这里具体指的就是:组成像素单个点的深度(既每个通道深度),一般都是无符号8位*//*一般图像概念所说的多少位位图是指像素的深度,如一个RGB位图就是 3*8=24,所以是24位位图;ARGB就是4*8=32,所以是32位位图;8位位图就是一个通道(一个单点)所有就是8位(既256色位图)*/

charcolorModel[4];                    /*颜色模式,有Gray、RGB、RGBA、CMYK等*/

charchannelSeq[4];                    /*通道顺序,如“RGB”、“BGR”等*/

int dataOrder;                                   /*数据的排列方式,使用像素格式*/

int origin;                                  /*坐标原点,有左上角和左下角两种*/

int align;                                          /*图像数据的排列方式*/

int width;                                  /*图像的宽*/

int height;                                  /*图像的高*/

struct _IplROI*roi;                   /*指向ROI结构的指针,NULL表没有*/

struct _IplImage*maskROI;       /*指向ROI模板的指针,NULL表没有*/

void *imageId;                          /*用于应用中,对于本库,可忽略*/

struct_IplTileInfo *tileInfo;        /*该指针指向包含图像分解的信息*/

int imageSize;                            /*图像的大小*/

char *imageData;                      /*指向图像数据的指针*/

int widthStep;                           /*校准后的行字节数*/

intBorderMode[4];            /*边缘像素的模式*/

intBorderConst[4];                    /*表示四个边的常数*/

char*imageDataOrigin;             /*该指针指向完整的、没有校准的图像*/

} IplImage;

《OpenCV中IplImage图像格式与BYTE图像数据的转换 》

IplImage* iplImage;

BYTE*  data;

1 由IplImage*得到BYTE*图像数据:

data = iplImage->imageDataOrigin; //未对齐的原始图像数据

或者

data = iplImage->imageData; //已对齐的图像数据

2 由BYTE*得到IplImage*图像数据

iplImage = cvCreateImageHeader(cvSize(width,height),depth,channels);

cvSetData(iplImage,data,step);

首先由cvCreateImageHeader()创建IplImage图像 头,制定图像的尺寸,深度和通道数;然后由

cvSetData()根据 BYTE*图像数据指针设置IplImage图像头的数据数据,其中step指定该IplImage图像

每行占的字节数,对于1通道的 IPL_DEPTH_8U图像,step可以等于width。

1,如果是从新创造一个Iplimage,则用IplImage* cvCreateImage( CvSize size, int depth, int

channels ),它创建头并分配数据。

注:当不再使用这个新图像时,要调用void cvReleaseImage( IplImage** image )将它的头和图像数

据释放!

2,如果有图像数据没有为图像头分配存储空间(即,没有为IplImage* 指针分配动态存储空间),则

先调用IplImage* cvCreateImageHeader( CvSize size, int depth, int channels )创建图像头,再

调用void cvSetData( CvArr* arr, void* data, int step )指定图像数据,可以理解为将这个新图

像的数据指针指向了一个已存在的图像数据上,不存在图像数据存储空间的分配操 作。

注:当不再使用这个新图像时,要调用void cvReleaseImageHeader( IplImage**image )将它的图像

头释放!

3,如果有图像数据也有图像头(用于IplImage为静态分配存储空间的情 况),则先调用IplImage*

cvInitImageHeader( CvSize size, int depth, int channels )更改图像头,再调用void

cvSetData( CvArr* arr, void* data, int step )指定图像数据。

注:因为这个新图像使用的是其它图像的数据和已有的图像头,所以不能使用 cvReleaseImage将它的

头和图像数据释放,也不能使用cvReleaseData将它的图像数据释 放!

4,如果从已有的一个图像创建,则用IplImage* cvCloneImage( const IplImage*image ),它制作

图像的完整拷贝包括头、ROI和数据。

注:当不再使用这个新图像时,要调用void cvReleaseImage( IplImage** image )将它的头和图像数

据释放!

下面是opencv的参考手册Mat类介绍:

Mat类

OpenCV c + + n 维稠密数组类

class CV_EXPORTS Mat

{

public:

/ / … …很多的方法...

...

/*!包括几位字段:

-神奇的签名

-连续性标志

-深度(Note:应该是位深)

-通道数

*/

int flags;(Note :目前还不知道flags做什么用的)

//!数组的维数,> = 2

int dims ;

//!行和列的数量或 (-1,-1) 此时数组已超过 2 维

int rows,cols;

//!指向数据的指针

uchar *data ;

//!指针的引用计数器 ;

/ / 阵列指向用户分配的数据时,当指针为 NULL

int * refcount ;

/ / 其他成员

...

};

Mat类表示一个 n 维的稠密数值型的单通道或多通道数组。它可以用于存储实数或复数值的向量和矩阵、灰度或彩色图像、体素、向量场、点云、张量、直方图 (尽管较高维的直方图存储在SparseMat可能更好)。M 数组的数据布局是由阵列  M.step[]定义的,使元素的地址(i0,。。。。iM.dims-1),其中 0<= ik < M.size [k],可以计算为:

addr( Mi0 ;:::;iM.dims-1) = M.data+ M.step[ 0]*i0 + M.step[ 1] *i1 + .…+ M.step[ M:dims- 1] iM:dims- 1

2维的数组的情况下根据上述公式被减至:

addr( Mi,j)= M.data+ M.step[ 0]*i+ M.step[ 1] *j

请注意,M.step[i] > =M.step[i+1] (事实上,M.step[i] > =M.step[i+1]*M.size[i+1])。这意味着2维矩阵是按行存储的,3 维矩阵是由平面存储,以此类推。M.step[M.dims-1] 是最小的而且总是等于元素大小M.elemSize()。因此,Mat中的数据布局完全兼容OpenCV 1.x 中CvMat、 IplImage、 CvMatND类型。它也和标准工具包和SDK,如Numpy(ndarray),Win32(独立设备位图)等主流的密集数组类型相兼容,也就是说,与任何使用步进(或步长)来计算像素位置的阵列相兼容。由于这种兼容性,使用户分配的数据创建Mat头以及用OpenCV函数实时处理该头成为可能。有很多不同的方法,创建一个Mat的对象。下面列出了最常见的选项:

使用 create(nrows,ncols,type)方法或类似的Mat(nrows,ncols,type [,fillValue])构造函数。一个新的指定了大小和类型的数组被分配。type和cvCreateMat 方法中的type参数具有相同的含义。例如,CV_8UC1 是指一个 8 位单通道阵列,CV_32FC2 指 2 通道(复平面)浮点阵列,以此类推。

//创建一个用1+3j填充的 7 x 7 复矩阵。

Mat  M(7,7,CV_32FC2,Scalar(1,3)) ;

/ /现在将 M转换为100 x 60的CV_8UC(15)的矩阵。

/ / 旧内容将会被释放

M.create(100,60,CV_8UC(15)) ;

这一章导言中指出,当当前的数组与指定的数组的形状或类型create() 分配唯一的新数组时的形状或类型。

创建多维数组:

/ / 创建 100 x 100 x 100 8 位数组

int sz[] = {100, 100, 100};

Mat. bigCube (3,sz,CV_8U,Scalar::all(0)) ;它将维度数(= 1)传递给Mat的构造函数,但列数设置为 1时,创建数组将是 2 维的。因此,Mat::dims 始终是>=2的(该数组为空时,也可以是 0)。

使用的复制构造函数或赋值运算符可以是一个数组或右侧的表达式(请参阅下图)。正像在导言中指出的,数组赋值运算复杂度是O(1)因为当你需要它的时候,它仅复制头和增加引用计数。Mat::clone() 方法可用于获取全(深)的副本数组。

为另一个数组的一部分构建头。它可以是单个行、 单个列,几个行,几个列,矩形区域(代数中称为较小值) 的数组或对角线。这种操作也是复杂度为O(1),因为,新头引用相同的数据。实际上,您可以使用此特性修改该数组的一部分例如:

/ /第 5行,乘以 3,加到第 3 行,

M.row(3) = M.row(3) + M.row (5) * 3 ;

/ / 现在将第7列复制到第1列

/ / M.col(1) = M.col(7) ;/ / 这个不能实现。

Mat  M1= M.col(1) ;

M.col(7).copyTo(M1) ;

/ / 创建一种新的 320 x 240 图像

Mat img(Size(320,240),CV_8UC3) ;

/ / 选择ROI(region of interest)

Mat roi(img,Rect(10,10,100,100)) ;

/ / 填充 (0,255,0) 的ROI (这是RGB 空间中的绿色);

/ / 320 x 240 原始图像将被修改。

roi = Scalar(0,255,0) ;

Scalar 是个short型vector。指定这个能够使用指定的定制化值来初始化矩阵。当然,如果你需要更多通道数,你可以使用大写的宏并把通道数放在小括号中,如下所示

  • 在 C\C++ 中通过构造函数进行初始化

        int sz[3] = {2,2,2}; 
        Mat L(3,sz, CV_8UC(1), Scalar::all(0));

由于额外的 datastart 和 dataend 的成员,它们使得用locateROI() 计算子数组在主容器数组中的相对的位置成为可能:

Mat A = Mat::eye ( 10, 10, CV_32S);

/ / 提取 A 的1 (含)到 3 (不包含)列。

Mat B = A(Range::all(),Range(1,3)) ;

/ / 提取 B 的5 (含)到 9 (不包含)行。

/ /即 C ~ A(Range(5,9),Range (1,3))

Mat C = B(Range(5,9),Range::all()) ;

Size size;Point ofs;

C.locateROI (size,ofs);

/ / size将变为 (width= 10,height= 10),ofs会变为 (x = 1,y = 5)

考虑到整个矩阵,如果您需要深层副本,使用子矩阵的sclone() 方法的提取。

为用户分配数据创建矩阵头。有利于执行下列操作:

1. 使用 OpenCV处理"外来"的数据(例如,当您执行 DirectShow *filter 或 gstreamer的pro-cessing 模块,等等)。例如:

void process_video_frame (const unsignedchar * pixels,

int width,int height,int step)

{

Mat img (width,height, CV_8UC3,pixels,step);

GaussianBlur (img,img ,Size(7,7),1.5,1.5) ;

}

2.快速初始化小矩阵和/或获取超快的元素的访问。

double m[3] [3] = {{a,b,c},{d,e,f} {g, h, i}}};

Mat M = Mat(3,3,CV_64F,m).inv() ;

本例中用户分配数据的一些很常见情况是从CvMat 和 IplImage 转换到Mat。为达到此目的,有些特殊的构造函数以指向CvMat 或 IplImage 和flag可选参数指示是否数据复制。从Mat到 CvMat 或 IplImage 的后台转换是通过类型转换运算符 Mat::operator CvMat() const 和 Mat::operator IplImage()实现的。operators不要复制数据。

IplImage * img = cvLoadImage("greatwave.jpg",1) ;

Mat mtx(img) ;/ / IplImage *-> Mat

CvMat oldmat = mtx ;/ / Mat-> CvMat

CV_Assert (oldmat.cols = = img-> width&& oldmat.rows = = img-> height & &

oldmat.data.ptr = = (uchar *) img->imageData & & oldmat.step = = img-> widthStep);

使用 MATLAB 样式数组初始值设定项zeros()、 ones()、 eye(),例如:

/ / 创建具双精度标识矩阵并将其添加到M。

M + = Mat::eye (M.rows,M.cols,CV_64F);

使用逗号分隔的初始值设定项:

/ / 创建 3 x 3 双精度恒等矩阵

Mat M = (Mat_ <double> (3,3) <<1,0,0,0,1,0,0,0,1) ;

使用此方法,您首先调用具有适当的参数的 Mat_类构造函数,然后只要把 << 运算符后面的值用逗号分隔,这些值可以是常量、变量、 表达式,等等。此外请注意所需的额外的圆括号((Mat_<double> (3,3)<< 1,0,0,0,1,0,0,0,1))以免出现编译错误。

数组一旦创建起来,它可以自动通过引用计数的机制被管理。如果数组头是在用户分配的数据的基础上构建的,您应该自己处理这些数据。当没有指向它的引用时,数组中的数据将被释放。如果在数组的析构函被调用之前要释放一个由矩阵头指向的数据,请使用Mat::release()。

掌握Array类的另一个重要的环节是元素的访问。本手册已经描述了如何计算每个数组元素的地址。通常情况下,不需要在代码中直接使用的公式。如果你知道数组元素类型(它可以使用 Mat::type() 方法检索得到),您可以用以下方式访问二维数组的元素Mij:

M.at <double>(i,j)  + = 1.f ;

假定 M 一个双精度浮点型数组。有几个变体的不同方法来针对不同的维度数进行处理。

如果您要处理整行的二维数组,最有效的方式是获取该行的头指针然后只需使用普通的 C运算符[]:

/ / 正矩阵元素之和计算

/ / (假定M 是一个双精度矩阵)

double sum = 0;

for (int i = 0 ;i < M.rows ; i + +)

{

const double *Mi = M.ptr <double> (i) ;

     for (int j = 0; j < M.cols ; j + +)

sum + = std::max(Mi [j],0.) ;

}

以上的操作中,某些操作实际上不依赖该数组的形状。他们只是一个接一个(或多个具有相同的坐标的多个数组中的元素,例如,数组相加)地处理数组元素。这种操作称为 元素指向(element-wise)。检查是否所有的输入/输出阵列是连续的,即有没有间断在每行的结尾,是有意义的。如果是的话,将它们(这些数组)作为单独的一个长行来处理:

/ / 计算正矩阵元素,优化的变量的总和

double sum = 0;

int cols =M.cols,rows = M.rows ;

if(M.isContinuous())

{

    cols * = rows ;

    rows = 1 ;

}

for (int i = 0 ;i < rows; i + +)

{

const double * Mi = M.ptr <double>(i) ;

for (int j = 0; j < cols ; j ++)

   sum + = std::max (Mi [j],0.) ;

}

对于连续的矩阵来说,外部循环体只需一次执行。所以,开销是规模较小,

小型矩阵的情况下尤其明显。

最后,还有足以成功跳过连续的行之间的间隔智能的STL 样式迭代器:

/ / 计算正矩阵元素和基于迭代器类型的变量之和

double sum = 0;

Mat Const Iterator_ <double> it =M.begin <double> (),it_end = M.end <double> () ;

for(; it! = it_end ; ++it)

sum+ = std::max (*it,0.);

矩阵迭代器是随机存取的迭代器,所以他们可以被传递给任何 STL 算法,包括 std::sort()。

矩阵表达式

这是已经实现的可以组合在任意复杂的表达式中的矩阵运算操作, (此处 A 、B 的表示矩阵 (Mat)、 s表示标量(Scalar),alpha为实数标量 (双精度型):

  加法、减法、求反: A + B + A-B、 A + s、 A-s、 s + A、 s-A、-A;

  缩放: A * alpha

  每个元素乘法和除法: A.mul (B)、 A / B,alpha/A

  矩阵相乘: A * B

  大动脉转位: A.t() (指在)

 矩阵反演和伪反演,求解线性系统和最小二乘问题:

A.inv([method]) (~ A-1) , A.inv([method])*B (~ X: AX=B)

  比较: cmpop B、 cmpop alpha、 alpha cmpop A,其中 cmpop 是以下几种运算符之一: >,> =,= =,! =,< =,<。比较的结果是其元素设置为 255的 8 位单通道掩码(如果特殊元素对满足条件) 或 0。

  按位逻辑运算: logicop B、 logicop s slogicop A、 ~ A,其中 logicop 是以下运算符之一: &,|, ^.

  元素的最小值和最大值:分 (A、 B)、 民 (,alpha),最大值 (A,B),最大 (,alpha)

  元素的绝对价值: abs(A)

  叉乘,点乘: A.cross(B) A.dot(B)

  任何标量与矩阵或矩阵的函数,返回一个矩阵或标量(scalar),如norm、, mean、 sum、countNonZero、trace、determinant、repeat和其他。

  矩阵初始值设定项(Mat::eye(),Mat::zeros(),Mat::ones())、矩阵以逗号分隔的初始值设定项、可提取sub-matrices的m atrix构造函数和运算符,(请参见Mat的说明)。

  Mat_ <destination_type> () 构造函数将结果强制转换为适当的类型。

Note:有些逗号分隔初始值设定项和一些其他的运算符可能需要显示调用Mat();或Mat_<T>();的构造函数来解决可能产生的歧义。

         以下是一些矩阵表达式的例子:

//计算矩阵A的伪反演等价于A.inv(DECOMP_SVD)

SVD svd(A);

Mat pinvA =svd.vt.t()*Mat::diag(1./svd.w)*svd.u.t();

//计算莱文伯格-马夸特算法中的参数的新向量

x -= (A.t()*A +lambda*Mat::eye(A.cols,A.cols,A.type())).inv(DECOMP_CHOLESKY)*(A.t()*err);

//用“Unsharp Mask”算法锐化图像

Mat blurred; double sigma = 1, threshold =5, amount = 1;

GaussianBlur(img, blurred, Size(), sigma,sigma);

Mat lowConstrastMask = abs(img - blurred)< threshold;

Mat sharpened = img*(1+amount) +blurred*(-amount);

img.copyTo(sharpened, lowContrastMask);

下面正式讲解Mat的各种方法。

Mat:: Mat

各种Mat构造函数。

C++: Mat::Mat()

C++: Mat::Mat(int rows, int cols, int type)

C++: Mat::Mat(Size size, int type)

C++: Mat::Mat(int rows, int cols, int type,const Scalar& s)

C++: Mat::Mat(Size size, int type, constScalar& s)

C++: Mat::Mat(const Mat& m)

C++: Mat::Mat(int rows, int cols, int type,void* data, size_t step=AUTO_STEP)

C++: Mat::Mat(Size size, int type, void*data, size_t step=AUTO_STEP)

C++: Mat::Mat(const Mat& m, constRange& rowRange, const Range& colRange)

C++: Mat::Mat(const Mat& m, constRect& roi)

C++: Mat::Mat(const CvMat* m, boolcopyData=false)

C++: Mat::Mat(const IplImage* img, boolcopyData=false)

C++: template<typename T, int n>explicit Mat::Mat(const Vec<T, n>& vec, bool copyData=true)

C++: template<typename T, int m, intn> explicit Mat::Mat(const Matx<T, m, n>& vec, bool copyData=true)

C++: template<typename T> explicitMat::Mat(const vector<T>& vec, bool copyData=false)

C++: Mat::Mat(const MatExpr& expr)

C++: Mat::Mat(int ndims, const int* sizes,int type)

C++: Mat::Mat(int ndims, const int* sizes,int type, const Scalar& s)

C++: Mat::Mat(int ndims, const int* sizes,int type, void* data, const size_t* steps=0)

C++: Mat::Mat(const Mat& m, constRange* ranges)

         参数

ndims– 数组的维数.

rows – 2维数组中行行数

cols – Number of columnsin a 2D array.

size – 2维数组的尺寸Size(cols, rows) .在Size()构造函数中行数和列数在次序上刚好反转过来了。

sizes–指定 n 维数组形状的整数数组。

type–数组的类型。表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位数)+(数据类型)+(通道数)。具体的有以下值:

CV_8UC1CV_8UC2CV_8UC3CV_8UC4
CV_8SC1CV_8SC2CV_8SC3CV_8SC4
CV_16UC1CV_16UC2CV_16UC3CV_16UC4
CV_16SC1CV_16SC2CV_16SC3CV_16SC4
CV_32SC1CV_32SC2CV_32SC3CV_32SC4
CV_32FC1CV_32FC2CV_32FC3CV_32FC4
CV_64FC1CV_64FC2CV_64FC3CV_64FC4
这里U(unsigned integer)表示的是无符号整数,S(signed integer)是有符号整数,F(float)是浮点数。
例如:CV_16UC2,表示的是元素类型是一个16位的无符号整数,通道为2.
C1,C2,C3,C4则表示通道是1,2,3,4
type一般是在创建Mat对象时设定,如果要取得Mat的元素类型,则无需使用type。

depth :矩阵中元素的一个通道的数据类型,这个值和type是相关的。例如 type为 CV_16SC2,一个2通道的16位的有符号整数。那么,depth则是CV_16S。depth也是一系列的预定义值,
将type的预定义值去掉通道信息就是depth值:
CV_8U CV_8S CV_16U CV_16S CV_32S CV_32F CV_64F

s–一个可选的初始化每个矩阵元素的参数。要在矩阵建成后将所有元素设置为特定值可以用Mat的赋值运算符Mat:operator=(constScala& value)。

data–指向用户数据的指针。矩阵构造函数传入data和step参数不分配矩阵数据。相反,它们只是初始化矩阵头指向指定的数据,这意味着没有数据的复制。此操作是很高效的,可以用来处理使用 OpenCV 函数的外部数据。外部数据不会自动释放,所以你应该小心处理它。

step–每个矩阵行占用的字节数。如果任何值应包括每行末尾的填充字节。如果缺少此参数(设置为 AUTO_STEP),假定没有填充和实际的步长用cols*elemSize()计算。请参阅Mat::elemSize()。

steps–多维数组(最后一步始终设置为元素大小) 的情况下的 ndims-1个步长的数组。如果没有指定的话,该矩阵假定为连续。

m–分配给构造出来的矩阵的阵列(作为一个整体或部分)。这些构造函数没有复制数据。相反,指向 m 的数据或它的子数组的头被构造并被关联到m上。引用计数器中无论如何都将递增。所以,当您修改矩阵的时候,自然而然就使用了这种构造函数,您还修改 m 中的对应元素。如果你想要独立的子数组的副本,请使用 Mat::clone()。

img –指向老版本的 IplImage图像结构的指针。默认情况下,原始图像和新矩阵之间共享数据。但当 copyData 被设置时,完整的图像数据副本就创建起来了。

vec–矩阵的元素构成的STL 向量。矩阵可以取出单独一列并且该列上的行数和矢量元素的数目相同。矩阵的类型匹配的向量元素的类型。构造函数可以处理任意的有正确声明的DataType类型。这意味着矢量元素不支持的混合型结构,它们必须是数据(numbers)原始数字或单型数值元组。对应的构造函数是显式的。由于 STL 向量不会自动转换为Mat实例,您应显式编写 Mat(vec)。除非您将数据复制到矩阵 (copyData = true),没有新的元素被添加到向量中,因为这样可能会造成矢量数据重新分配,并且因此使得矩阵的数据指针无效。

copyData –指定STL 向量或旧型 CvMat 或 IplImage是应复制到 (true)新构造的矩阵中 还是 (false) 与之共享基础数据的标志,复制数据时,使用Mat引用计数机制管理所分配的缓冲区。虽然数据共享的引用计数为 NULL,但是分配数据必须在矩阵被析构之后才可以释放。

rowRange – m 的行数的取值范围。正常情况下,范围开始端具有包容性和范围结束端是独占的。使用 Range::all() 来取所有的行。

colRange –m 列数的取值范围。使用 Range::all() 来取所有的列。

ranges –表示M沿每个维度选定的区域的数组。

expr – 矩阵表达式。请参见矩阵表达式。

以上这些都是Mat生成一个矩阵的各类构造函数。

未完。。。。。。。。。。。。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值