1. 重要类成员
- data:数据存储的起始地址 (uchar*类型);
- dims:矩阵维度。如 3 * 4 的矩阵为 2 维, 3 * 4 * 5 的为3维;
- channels():通道数量,矩阵中表示一个元素所需要的值的个数。例:3 * 4矩阵中共有12个元素,如果每个元素需要3个值表示,那么此矩阵的通道数为3。常见的是一张彩色图片有B蓝、G绿、R红3个通道;
- depth():深度,即表示单通道中元素值的位数(bits)。Mat.depth()返回的是一个 0~6 的数字,分别代表不同的位数:enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 }; 可见 0和1都代表8位, 2和3都代表16位,4和5代表32位,6代表64位;
- elemSize() : 单个元素在所有通道中大小之和,elemSize() = sizeof(数据类型) * channels()。如果Mat中的数据的数据类型是 CV_8U 那么 elemSize() = 1;CV_8UC3 那么 elemSize() = 3,CV_16UC2 那么 elemSize() = 4;
- elemSize1() : 单个元素在1个通道中的大小。elemSize1() = sizeof(数据类型) = elemSize() / channels()。
- step[]:可以看作是一个有dims个元素的动态数组,定义了矩阵的在各维度之间跳变时的最大步长(单位:字节。如2维Mat时,step[0]表示行长度,step[1]表示元素长度)。
- step1(n):与step[n]对应范围的总通道数, step1(n) = step[n] / elemSize1();
- type: 矩阵元素的数据类型
2. Mat.step
step的几个类别区分:
- step:矩阵第一行元素的字节数
- step[0]:矩阵第一行元素的字节数
- step[1]:矩阵中一个元素的字节数
- step1(0):矩阵中一行有几个通道数
- step1(1):一个元素有几个通道数(channel())
3. Mat的创建
Mat::Mat(); //default
Mat::Mat(int rows, int cols, int type);
Mat::Mat(Size size, int type);
Mat::Mat(int rows, int cols, int type, const Scalar& s);
Mat::Mat(Size size, int type, const Scalar& s);
Mat::Mat(const Mat& m);
//参数说明:
//int rows:高
//int cols:宽
//int type:参见"Mat类型定义"
//Size size:矩阵尺寸,注意宽和高的顺序:Size(cols, rows)
//const Scalar& s:用于初始化矩阵元素的数值
//const Mat& m:拷贝m的矩阵头给新的Mat对象,但是不复制数据!相当于创建了m的一个引用对象
//例子1:创建100*90的矩阵,矩阵元素为3通道32位浮点型
cv::Mat M(100, 90, CV_32FC3);
//例子2:使用一维或多维数组来初始化矩阵,
double m[3][3] = {
{a, b, c}, {d, e, f}, {g, h, i}};
cv::Mat M = cv::Mat(3, 3, CV_64F, m);
//2.使用create函数:
Mat a = create(10, 9, CV_16U); //创建10*9的矩阵,矩阵元素为16位无符号整型
//create的一个特殊用法:如果初始化的时候没有传入size的参数,或者后面需要改变size的参数,可以使用create来调整
// make 7x7 complex matrix filled with 1+3j.
cv::Mat M(7,7,CV_32FC2,Scalar(1,3));
// and now turn M to 100x60 15-channel 8-bit matrix.
// The old content will be deallocated:隐式使用release()释放
M.create(100,60,CV_8UC(15));
4. Mat的访问
at
//第一种方法
for(int h = 0 ; h < image.rows ; ++ h)
{
for(int w = 0 ; w < image.cols / 2 ; ++ w)
{
image.at<Vec3b>(h , w)[0] = 255 ;
image.at<Vec3b>(h , w)[1] = 0 ;
image.at<Vec3b>(h , w)[2] = 0 ;
}
}
imshow("color1" , image) ;
//方法二
for(int h = 0 ; h < image.rows ; ++ h)
{
for(int w = 0 ; w < image.cols / 2 ; ++ w)
{
Vec3b &bgr = image.at<Vec3b>(h , w) ;
bgr.val[0] = 0 ;
bgr.val[1] = 255 ;
bgr.val[2] = 0 ;
}
}
ptr
//三通道图像,at(y , x)索引是先行(y轴) , 后列(x轴)
//第一种方法
for(int h = 0 ; h < image.rows ; ++ h)
{
for(int w = 0 ; w < image.cols / 2 ; ++ w)
{
uchar *ptr = image.ptr<uchar>(h , w) ;
ptr[0] = 255 ;
ptr[1] = 0 ;
ptr[2] = 0 ;
}
}
imshow("color1" , image) ;
//第二种方法
for(int h = 0 ; h < image.rows ; ++ h)
{
for(int w = 0 ; w < image.cols / 2 ; ++ w)
{
Vec3b *ptr = image.ptr<Vec3b>(h , w) ;
ptr->val[0] = 0 ;
ptr->val[1] = 255 ;
ptr->val[2] = 0 ;
}
}
//单通道图像,at(y , x)索引是先行(y轴) , 后列(x轴)
//第一种方法
for(int h = 0 ; h < image.rows ; ++ h)
{
uchar *ptr = image.ptr(h) ;
for(int w = 0 ; w < image.cols / 2 ; ++ w)
{
ptr[w] = 128 ;
}
}
for(int h = 0 ; h < image.rows ; ++ h)
{
for(int w = 0 ; w < image.cols / 2 ; ++ w)
{
uchar *ptr = image.ptr<uchar>(h , w) ;
*ptr = 255 ;
}
}
迭代器
//三通道图像
Mat_<Vec3b>::iterator it = image.begin<Vec3b>() ;
Mat_<Vec3b>::iterator itend = image.end<Vec3b>() ;
for(;it != itend ; ++ it)
{
(*it)[0] = 255 ;
(*it)[1] = 0 ;
(*it)[2] = 0 ;
}
//单通道图像
image = imread("forest.jpg" , 0) ;
Mat_<uchar>::iterator it1 = image.begin<uchar>() ;
Mat_<uchar>::iterator itend1 = image.end<uchar>() ;
for (;it1 != itend1 ; ++ it1)
{
(*it1) = 128 ;
}
data
data = image.data ;
for(int h = 0 ; h < image.rows ; ++ h)
{
for(int w = 0 ; w < image.cols/2 ; ++ w)
{
*data ++ = 128 ;
}
}
row, col
for(int i = 0 ; i < 100 ; ++ i)
{
image.row(i).setTo(Scalar(0 , 0 , 0)) ;//设定第i行数据
image.col(i).setTo(Scalar(0 , 0 , 0)) ;//设定第i列数据
}
综合高效
//单通道多通道都适用
int nRows = image.rows ;
int nCols = image.cols * image.channels() ;
if(image.isContinuous())
{
nCols = nRows * nCols ;
nRows = 1 ;
}
for(int h = 0 ; h < nRows ; ++ h)
{
uchar *ptr = image.ptr<uchar>(h) ;
for(int w = 0 ; w < nCols ; ++ w)
{
*ptr ++ = 128 ;
}
}
5. Mat的数据类型
当使用at以及对数据进行运算时候需要指定类型。cv::Mat 类的对象有一个成员函数type()用来返回矩阵元素的数据类型
访问:
cv::Vec3b vec3b = img.at<cv::Vec3b>(0,0);
uchar vec3b0 = img.at<cv::Vec3b>(0,0)[0];
uchar vec3b1 = img.at<cv::Vec3b>(0,0)[1];
uchar vec3b2 = img.at<cv::Vec3b>(0,0)[2];
定义:
typedef Vec<uchar, 2> Vec2b;
typedef Vec<uchar, 3> Vec3b;
typedef Vec<uchar, 4> Vec4b;
typedef Vec<short, 2> Vec2s;
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;
typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<float, 2> Vec2f;
typedef Vec<float, 3> Vec3f;
typedef Vec<float, 4> Vec4f;
typedef Vec<float, 6> Vec6f;
typedef Vec<double, 2> Vec2d;
typedef Vec<double, 3> Vec3d;
typedef Vec<double, 4> Vec4d;
typedef Vec<double, 6> Vec6d;