class CV_EXPORTS Mat
{
public:
/*flag参数中包含一些关于矩阵的信息:
——矩阵标识
——数据是否连续
——深度
——通道数目
*/
int flag;
//矩阵的维数,取值大于等于2
int dims;
//矩阵的行数和列数,如果矩阵超过二维,这两个变量的值都为-1
int rows,cols;
//指向数据的指针
uchar* data;
}
无参数构造函数:
Mat::Mat();
创造指定大小,类型type的图像
Mat::Mat(int rows,int cols,int type);
Mat::Mat(Size size,int type);
Mat::Mat(int ndims,const int *sizes,int type);
Mat::Mat(const std::vector& sizes,int type);
创建指定大小,类型type,所有元素都初始化为s值的图像
Mat::Mat(int rows,int cols,int type,const Scalar& s);
Mat::Mat(Size size,int type,const Scalar& s);
Mat::Mat(int ndims,const int* sizes,int type,const Scalar& s);
Mat::mat(const std::vector& sizes,int type,const Scalar& s);
创建指定大小,类型type,步长为step的图像
Mat::Mat(int rows,int cols,int type,void* data,size_t step=AUTO_STEP);
Mat::Mat(Size size,int type,void* data,size_t step=AUTO_STEP);
Mat::Mat(int ndims,const int* sizes,int type,void* data,size_t steps=0);
Mat::Mat(const std::vector& sizes,int type,void* data,const size_t* steps=0);(行步长指矩阵每行所占的字节数;此函数不创建内存,直接使用data所指的内存)
例子:
//创建行数为3,列数为2,类型为8位无符号整形,所有元素都初始化为(0,0,255)的三通道图像
Mat M(3,2,CV_8UC3,Scalar(0,0,255));
//创建行数为3,列数为2,通道数为5的图像
Mat M(3,2,CV_8UC(5));
创建大小,类型与m相同的图像
Mat::Mat(const Mat& m);
创建大小,类型与指定m部分相同的图像
Mat::Mat(const Mat& m,const Range& rowRange,const Range& colRange=Range::all());
Mat::Mat(const Mat& m,const Rect& roi);
Mat::Mat(const Mat& m,const Range* ranges);
Mat::Mat(const Mat& m,const std::vector& ranges);
Mat::create(int rows,int cols,int type);
Mat::create(Size size,int type);
Mat::create(int ndims,const int* sizes,int type);
Mat::create(const std::vector& sizes,int type);
//create()函数不能设置图像像素/矩阵元素的初始值
例子:
//构造函数创建图像
Mat M(3,2,CV_8UC3);
//释放内存重新创建图像
M.create(2,2,CV_8UC2);
注:create()函数指定的参数与当前的图像参数相同,则不进行内存申请,如果参数不同,则会减少当前图像数据内存的引索,并重新申请内存。
Mat::zeros(int rows,int cols,int type);
Mat::zeros(Size size,int type);
Mat::zeros(int ndims,const int* sz,int type);
Mat::ones(int rows,int cols,int type);
Mat::ones(Size size,int type);
Mat::ones(int ndims,const int* sz,int type);
Mat::eye(int rows,int cols,int type);
Mat::eye(Size size int type);
单通道和多通道图像的元素类型一般为8U,也可以为16S,32F等,这些类型可以uchar,short,float等基本数据类型表达。
对于M * N * C多通道图像,此时矩阵元素已经不是基本数据类型,而是一个向量。
OpenCV定义了一个模板类Vec,可用来表示一个向量
2/3/4维uchar向量
typedef Vec Vec2d;
typedef Vec Vec3d;
typedef Vec Vec4d;
Vec3d color;//描述RGB颜色的color变量
color[0]=255;//B分量
color[1]=0;//G分量
color[2]=0;//R分量
at函数为模板函数,它返回指定矩阵元素的引用
tips:at()函数优点是代码可读性高,但是函数效率不是很高,并不推荐使用at()函数遍历图像。at()函数只在debug模式下进行越界检查。
Mat类支持C++ STL库中的迭代器(iterator)进行遍历
Mat gray(480,640,CV_8UC1);
MatIterator grayItr,grayEnd;
for(grayItr = gray.begin(),
grayEnd = gray.end();
grayItr!=grayEnd;grayItr++)
*grayItr=rand()%255;
Mat gray(480,640,CV_8UC1);
for(int i=0;i(i);
for(int j=0;j
tips:在重视程序速度的情况下,建议使用指针进行遍历。如果指针访问出错,程序运行时可能出现“段错误”(segment fault)
Mat::row(int y)const;
Mat::col(int x)const;
//取出A矩阵的第i行
Mat line =A.row(i);
//取出A中数据的第i行将这行乘2后赋值给第j行
A.row(j) A.row(i)*2;
通过使用Range类,可以选取矩阵的多行或多列
//创建一个单位阵
Mat A=Mat::eye(10,10,CV_32S);
//提取全部行和1到3列(不包括第3列)
Mat B=A(Range::all(),Range(1,3));
//提取5到9行(不包括第9行),提取全部列
Mat C=B(Range(5,9),Range::all());
//可直接写为
Mat A=Mat::eye(10,10,CV_32S);
Mat C=A(Range(5,9),Range(1,3));
可使用Rect()类
//创建宽为320,高度为240的3通道图像
Mat img(320,240,CV_8UC3);
//选取img中的Rect(10,10,100,100)的区域为ROI
//使用构造函数
Mat roi(img,Rect(10,10,100,100));
Mat roi2(img,Range(10,100),Range(10,100));
Mat roi3=img(Rect(10,10,100,100));
Mat roi4=img(Range(10,100),Range(10,100));
Mat::diag(int d=0)const
tips:选取局部区域的方法都不进行内存的复制操作,新对象与原始对象共享相同的数据区域,因此执行速度快。
Mat类重载的<<操作符,可以使用流操作输出矩阵内容,并支持不同的输出格式
Mat R(3,2,CV_8UC3);
randu(R,Scalar::all(0),Scalar::all(255));
cout<
——加减取负:A+B,A+s,s+A,-A
——缩放:A*alpha
——对应元素的乘除:A.mul(B),A/B,alapha/A
——矩阵乘法:A*B
——转置:A.t()
——求逆和求伪逆A.inv()
——比较运算:A cmpop B,alpha cmpop A(cmpop可为>,>=,==,!=,<)。若条件成立,结果矩阵的对应元素被置为255,否则为0。
——位逻辑运算:A logicop B,A logicop s ,s logicop A,~A(logicop可为&,|和^)
——对应元素的最大最小:min(A,B),min(A,alpha),max(A,B) ,max(A,alpha)
——元素的绝对值:abs(A)
——叉乘和点乘:A.cross(B),A.dot(B)
Mat_ 类是对Mat类的一个轻量级包装,它是一个模板类,使得访问元素不需要指定元素类型。减少出错可能。
Mat grayImg(480,640,CV_8UC1);
Mat_ grayImg1=(Mat_ &)grayImg;
for(int i=0;i
Mat 类由两个数据部分组成:矩阵头和一个指向所有像素值的内存的指针uchar* data。
OpenCV使用了引用计数机制,既让矩阵指针data指向同一地址,同时引用计数增加。OpenCV中很多函数及很多操作只复制矩阵头信息,而不复制矩阵数据。
Mat cv::imread(const String &fliname,int flags=IMREAD_COLOR);
filename:图片文件的绝对或相对路径
flags:读取图片的的形式(灰度/彩色/alpha通道)
(cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略alpha通道,可以直接写1
cv2.IMREAD_GRAYSCALE:读入灰度图片,可以直接写0
cv2.IMREAD_UNCHANGED:顾名思义,读入完整图片,包括alpha通道,可以直接写-1)
return:读取的图像数据
void cv::imshow(const String& winname,InputArray mat);
winname:显示图片的窗口的名称
mat:要显示的图像
Mat cv::imwrite(const String& filename,
InputArray img,
const std::vector& params=std::vector());
filename:图像保存为文件的文件名
img:要保存的图像数据
params:附加信息,如指定JPEG压缩质量等
void cv::resize(InputArray src,
OutputArray dst,
Size size,
double fx=0,
double fy=0,
int interpolation=INTER_LINEAR);
src:输入图像
dst:输出缩放的图像
dsize:输出图像的大小
fx:沿水平方向的缩放因子
fy:沿竖直方向的缩放因子
interpolation:插值方式(INTER_LINEAR,INTER_NEAREST,etc)
void cv::split(const &src,Mat* mvbegin);
src:输入的多通道图像
mvbegin:输出矩阵,矩阵个数等于src.channels()
void cv::merge(const Mat* mv,size_t count,OutputArray dst);
mv:要合并的矩阵,所有矩阵的大小和数据类型必须相同
count:当mv是一个矩阵时输入矩阵个数,值必须大于0
dst:输出矩阵,大小和数据类型与mv[0]相同,矩阵的通道数为count
void cv::inRange(InputArray src,InputArray lowerb,InputArray upperb,OutputArray dst);
src:输入图像
lowerb:下边界矩阵或数值
upperb:上边界矩阵或数值
dst:输出类型为CV_8U的图像,大小与输入类型相同
//绘制直线
void cv::line(InputOutArray img,Point pt1,Point pt2,const Scalar& color,
int thickness=1,int lineType=LINE_8,int shift=0);
//绘制圆
void cv::circle(InputoutArray img,Point center,int rsdius,const Scalar& color,int thickness=1,
int lineType=LINE_8,int shift=0);
//绘制矩形
void cv::rectangle(InputOutputArray img,Point pt1,Point pt2,const Scalar& color,int thickness=1,
int lineType=LINE_8,int shift=0);
void cv::rectangle(InputOutputArray img,Rect rect,const Scalar& color,int thickness=1,int lineType=LINE_8,int shift=0);
//绘制文字
void cv::putText(InputOutputArray img,const String& text,Point org,int fontFace,double fontScale,
Scalar color,int thickness=1,int lineType=LINE_8,bool bottomLeftOrigin=false);