C++ - cv::Mat数据类型 + 提取某些行或列
简介
1、cv::Mat 数据类型
2、cv::Mat 提取某些行或列
cv::Mat 数据类型
在以下两个场景中使用OpenCV时,我们必须事先知道矩阵元素的数据类型:
1、使用 at 方法访问数据元素的时候要指明数据类型
2、做数值运算的时候,比如究竟是整数除法还是浮点数除法。
cv::Mat 类的对象有一个成员函数type()用来返回矩阵元素的数据类型,返回值是 int 类型,不同的返回值代表不同的类型,具体对应关系如下所示:
表头的 C1, C2, C3, C4 指的是通道(Channel)数,例如:
1、灰度图像只有 1 个通道,是 C1;
2、JPEG格式 的 RGB 彩色图像就是 3 个通道,是 C3
3、PNG 格式的彩色图像除了 RGB 3个通道外,还有一个透明度通道,所以是 C4。
如果仅仅是为了在数值计算前明确数据类型,那么看到这里就可以了
如果是要使用 at 方法访问数据元素,那么还需要下面一步
因为以单通道为例,at 方法接受的是 uchar 这样的数据类型,而非 CV_8U。
在已知通道数和每个通道数据类型的情况下,指定给 at 方法的数据类型如下表所示:
现在,就可以使用at来访问图像的像素了:
1 cv::Vec3b vec3b = img.at<cv::Vec3b>(0,0); 2 uchar vec3b0 = img.at<cv::Vec3b>(0,0)[0]; 3 uchar vec3b1 = img.at<cv::Vec3b>(0,0)[1]; 4 uchar vec3b2 = img.at<cv::Vec3b>(0,0)[2]; 5 std::cout<<"vec3b = "<<vec3b<<std::endl; 6 std::cout<<"vec3b0 = "<<(int)vec3b0<<std::endl; 7 std::cout<<"vec3b1 = "<<(int)vec3b1<<std::endl; 8 std::cout<<"vec3b2 = "<<(int)vec3b2<<std::endl;
上述数据类型以及取值范围
Vec类的定义
1 template<typename _Tp, int n> class Vec : public Matx<_Tp, n, 1> {...}; 2 3 typedef Vec<uchar, 2> Vec2b; 4 typedef Vec<uchar, 3> Vec3b; 5 typedef Vec<uchar, 4> Vec4b; 6 7 typedef Vec<short, 2> Vec2s; 8 typedef Vec<short, 3> Vec3s; 9 typedef Vec<short, 4> Vec4s; 10 11 typedef Vec<int, 2> Vec2i; 12 typedef Vec<int, 3> Vec3i; 13 typedef Vec<int, 4> Vec4i; 14 15 typedef Vec<float, 2> Vec2f; 16 typedef Vec<float, 3> Vec3f; 17 typedef Vec<float, 4> Vec4f; 18 typedef Vec<float, 6> Vec6f; 19 20 typedef Vec<double, 2> Vec2d; 21 typedef Vec<double, 3> Vec3d; 22 23 typedef Vec<double, 4> Vec4d; 24 typedef Vec<double, 6> Vec6d;
cv::Mat 提取某些行或列
Mat::rowRange
Creates a matrix header for the specified row span.
C++: Mat Mat:: rowRange (int startrow, int endrow ) const C++: Mat Mat:: rowRange (const Range& r ) const Parameters: startrow – An inclusive 0-based start index of the row span. endrow – An exclusive 0-based ending index of the row span. r – Range structure containing both the start and the end indices.
The method makes a new header for the specified row span of the matrix. Similarly to Mat::row() and Mat::col() , this is an O(1) operation.
Mat::colRange
Creates a matrix header for the specified column span.
C++: Mat Mat:: colRange (int startcol, int endcol ) const C++: Mat Mat:: colRange (const Range& r ) const Parameters: startcol – An inclusive 0-based start index of the column span. endcol – An exclusive 0-based ending index of the column span. r – Range structure containing both the start and the end indices.
The method makes a new header for the specified column span of the matrix. Similarly to Mat::row() and Mat::col() , this is an O(1) operation.
由于这两个函数返回的是指向原矩阵内部位置的指针,所以最好再利用clone()函数进行数据拷贝创建新的矩阵,代码如下:
1 #include <opencv2/core/core.hpp> 2 #include <opencv2/highgui/highgui.hpp> 3 #include <iostream> 4 5 using namespace cv; 6 using namespace std; 7 8 int main(){ 9 Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); 10 cout << "Total matrix:" << endl; 11 cout << C << endl; 12 13 Mat row = C.rowRange(1,3).clone(); 14 cout << "Row range:" << endl; 15 cout << row << endl; 16 17 Mat col = C.colRange(1,3).clone(); 18 cout << "Col range:" << endl; 19 cout << col << endl; 20 }
结果如下: Total matrix [0, -1, 0; -1, 5, -1; 0, -1, 0] Row range: [-1, 5, -1; 0, -1, 0] Col range: [-1, 0; 5, -1; -1, 0]
这两个函数很有趣,它们让我实现不用调用opencv特有函数来实现相应功能,而是自己可以写函数随机应变地实现自己所需的任何图像方面功能
附录: