多通道的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