在以下兩個(gè)場(chǎng)景中使用 OpenCV 時(shí),我們必須事先知道矩陣元素的數(shù)據(jù)類(lèi)型:
1,使用 at 方法訪(fǎng)問(wèn)數(shù)據(jù)元素的時(shí)候要指明數(shù)據(jù)類(lèi)型
2,做數(shù)值運(yùn)算的時(shí)候,比如究竟是整數(shù)除法還是浮點(diǎn)數(shù)除法。
但面對(duì)一大堆代碼,我們有時(shí)并不清楚當(dāng)前的矩陣元素究竟是什么類(lèi)型,這篇文章就是以cv::Mat 類(lèi)為例來(lái)解決這個(gè)問(wèn)題。
cv::Mat 類(lèi)的對(duì)象有一個(gè)成員函數(shù) type() 用來(lái)返回矩陣元素的數(shù)據(jù)類(lèi)型,返回值是 int 類(lèi)型,不同的返回值代表不同的類(lèi)型。OpenCV Reference Manual 中對(duì) type() 的解釋如下所示:
Mat::type
C++: int Mat::type() const
The method returns a matrix element type. This is an identifier compatible with the CvMat type system, like CV_16SC3 or 16-bit signed 3-channel array, and so on.
至此,知道了 函數(shù),下一步更關(guān)鍵的就是返回值和具體類(lèi)型之間的對(duì)應(yīng)關(guān)系了。文章《[LIST OF MAT TYPE IN OPENCV][LIST OF MAT TYPE IN OPENCV]》對(duì)此整理得非常清楚,具體如下表所示:
| C1 | C2 | C3 | C4 | |
|---|---|---|---|---|
| CV_8U | 0 | 8 | 16 | 24 |
| CV_8S | 1 | 9 | 17 | 25 |
| CV_16U | 2 | 10 | 18 | 26 |
| CV_16S | 3 | 11 | 19 | 27 |
| CV_32S | 4 | 12 | 20 | 28 |
| CV_32F | 5 | 13 | 21 | 29 |
| CV_64F | 6 | 14 | 22 | 30 |
表頭的 C1, C2, C3, C4 指的是通道(Channel)數(shù),比如灰度圖像只有 1 個(gè)通道,是 C1;JPEG格式 的 RGB 彩色圖像就是 3 個(gè)通道,是 C3;PNG 格式的彩色圖像除了 RGB 3個(gè)通道外,還有一個(gè)透明度通道,所以是 C4。大家還會(huì)發(fā)現(xiàn) 7 怎么沒(méi)有被定義類(lèi)型,這個(gè)可以看 OpenCV 源碼,有如下所示的一行,說(shuō)明 7 是用來(lái)給用戶(hù)自定義的:
#define CV_USRTYPE1 7
如果僅僅是為了在數(shù)值計(jì)算前明確數(shù)據(jù)類(lèi)型,那么看到這里就可以了;如果是要使用 at 方法訪(fǎng)問(wèn)數(shù)據(jù)元素,那么還需要下面一步。因?yàn)橐詥瓮ǖ罏槔?strong>at 方法接受的是 uchar 這樣的數(shù)據(jù)類(lèi)型,而非 CV_8U。在已知通道數(shù)和每個(gè)通道數(shù)據(jù)類(lèi)型的情況下,指定給 at 方法的數(shù)據(jù)類(lèi)型如下表所示:
| C1 | C2 | C3 | C4 | C6 | |
|---|---|---|---|---|---|
| uchar | uchar | cv::Vec2b | cv::Vec3b | cv::Vec4b | |
| short | short | cv::Vec2s | cv::Vec3s | cv::Vec4s | |
| int | int | cv::Vec2i | cv::Vec3i | cv::Vec4i | |
| float | float | cv::Vec2f | cv::Vec3f | cv::Vec4f | cv::Vec6f |
| double | double | cv::Vec2d | cv::Vec3d | cv::Vec4d | cv::Vec6d |
至此,我們就可以像《OpenCV for Matlab Users (2)》中演示的一樣采用如下方式訪(fǎng)問(wèn)圖像(矩陣)了
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];
std::cout<<"vec3b = "<<vec3b<<std::endl;
std::cout<<"vec3b0 = "<<(int)vec3b0<<std::endl;
std::cout<<"vec3b1 = "<<(int)vec3b1<<std::endl;
std::cout<<"vec3b2 = "<<(int)vec3b2<<std::endl;
附錄
| 數(shù)值 | 具體類(lèi)型 | 取值范圍 |
|---|---|---|
| CV_8U | 8 位無(wú)符號(hào)整數(shù) | (0…..255) |
| CV_8S | 8 位符號(hào)整數(shù) | (-128…..127) |
| CV_16U | 16 位無(wú)符號(hào)整數(shù) | (0……65535) |
| CV_16S | 16 位符號(hào)整數(shù) | (-32768…..32767) |
| CV_32S | 32 位符號(hào)整數(shù) | (-2147483648……2147483647) |
| CV_32F | 32 位浮點(diǎn)數(shù) | (-FLT_MAX ………FLT_MAX,INF,NAN) |
| CV_64F | 64 位浮點(diǎn)數(shù) | (-DBL_MAX ……….DBL_MAX,INF,NAN) |
Vec 類(lèi)的定義
template<typename _Tp, int n> class Vec : public Matx<_Tp, n, 1> {...};
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;
轉(zhuǎn)載:http://www.itdecent.cn/p/204f292937bb