多通道的Mat类矩阵是一个类似于三维的数据,而计算机的存储空间是一个二维空间,因此Mat类矩阵在计算机存储时是将三维数据变成二维数据,先存储第一个元素每个通道的数据,之后再存储第二个元素每个通道的数据。每一行的元素都按照这种方式进行存储,因此如果我们找到了每个元素的起始位置,便可以找到这个元素中每个通道的数据
Mat类常用的属性
Mat a = Mat(3, 4, CV_32FC3); //3通道32位
cout << a.channels() << endl; //通道数
cout << a.total() << endl; //输出数组总元素
cout << a.elemSize() << endl; //输出每个元素的字节数
cout << a.step<< endl; //step = elemSize*cols 以字节为单位的矩阵的有效宽度
cout << a.cols << endl; //图像的列数 如果要算矩阵的列数 需要乘通道数
cout << a.rows << endl; //行数
利用at读取操作矩阵的元素
Mat a = (cv::Mat_<uchar>(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
a.at<uchar>(0, 0) = 10; //可以通过at访问矩阵元素并可以修改值
在openCV 中,针对3通道矩阵,定义了cv::Vec3b、cv::Vec3s、cv::Vec3w、cv::Vec3d、cv::Vec3f、cv::Vec3i
六种类型用于表示同一个元素的三个通道数据。通过这六种数据类型可以总结出其命名规则,其中的数字表示通道的个数,
最后一位是数据类型的缩写,b是uchar类型的缩写、s是short类型的缩写、w是ushort类型的缩写、d是double类型的缩写、f是float类型的缩写、 i是int类型的缩写。当然OpenCV也为2通道和4通道定义了对应的变量类型,其命名方式也遵循这个命名规则,例如2通道和4通道的uchar类型分别用cv::Vec2b和cv::Vec4b表示
Mat b(3, 4, CV_8UC3, Scalar(1, 255, 0));
cv::Vec3b vc3 = b.at<cv::Vec3b>(0, 0); //选取第0号元素 由此可以抽象为3维数组
int first = (int)vc3.val[0]; //访问到的是0号元素的通道1数据 即B--Blue
int secend = (int)vc3.val[1]; //G
int third = (int)vc3.val[2]; //R
cout << first << endl;
cout << secend << endl;
cout << third << endl;
//可以直接用下面的写法
int first = b.at<Vec3b>(0,0)[0];
利用ptr指针读取元素
//利用指针ptr读取Mat类矩阵元素
Mat c(3, 4, CV_8UC3, Scalar(0, 0, 255));
for (int i = 0;i < c.rows;i++)
{
uchar* p = c.ptr<uchar>(i); //指针P指向首行
for (int j = 0;j < c.cols * c.channels();j++)
cout << (int)p[j] << endl; //定义的uchar类型 要强制转化为int类型
}
利用迭代器访问元素
//通过迭代器访问Mat类矩阵中的元素
Mat a(3, 4, CV_8UC1, Scalar(5));
// cv::MatIterator_<uchar> it = a.begin<uchar>();
// cv::MatIterator_<uchar> it_end = a.end<uchar>();
//
//迭代器只能访问单通道的图像数据
for (cv::MatIterator_<uchar> it = a.begin<uchar>();it != a.end<uchar>();it++)
cout << (int)(*it) << endl; //uchar 不能输出 要强制转为int