2015-04-30-確定 OpenCV 矩陣元素的數據類型

在以下兩個場景中使用 OpenCV 時,我們必須事先知道矩陣元素的數據類型:

  • 使用 at 方法訪問數據元素的時候要指明數據類型
  • 做數值運算的時候,比如究竟是整數除法還是浮點數除法。

但面對一大堆代碼,我們有時并不清楚當前的矩陣元素究竟是什么類型,這篇文章就是以 cv::Mat 類為例來解決這個問題。

cv::Mat 類的對象有一個成員函數 type() 用來返回矩陣元素的數據類型,返回值是 int 類型,不同的返回值代表不同的類型。OpenCV Reference Manual 中對 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.

實際的代碼如下所示:

cv::Mat haha = cv::Mat::zeros(3,3,CV_64F);
int hahaType = haha.type();
std::cout<<"hahaType = "<<hahaType<<std::endl;

至此,知道了 type() 函數,下一步更關鍵的就是返回值和具體類型之間的對應關系了。文章《[LIST OF MAT TYPE IN OPENCV][LIST OF MAT TYPE IN OPENCV]》對此整理得非常清楚,具體如下表所示:

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)數,比如灰度圖像只有 1 個通道,是 C1;JPEG格式 的 RGB 彩色圖像就是 3 個通道,是 C3;PNG 格式的彩色圖像除了 RGB 3個通道外,還有一個透明度通道,所以是 C4。大家還會發現 7 怎么沒有被定義類型,這個可以看 OpenCV 源碼,有如下所示的一行,說明 7 是用來給用戶自定義的:

#define CV_USRTYPE1 7

如果僅僅是為了在數值計算前明確數據類型,那么看到這里就可以了;如果是要使用 at 方法訪問數據元素,那么還需要下面一步。因為以單通道為例,at 方法接受的是 uchar 這樣的數據類型,而非 CV_8U。在已知通道數和每個通道數據類型的情況下,指定給 at 方法的數據類型如下表所示:

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)》中演示的一樣采用如下方式訪問圖像(矩陣)了

    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;

初寫于 2015-04-30.
首發于 Yimian Dai's Homepage,轉載請注明出處。

參考資料

  • [LIST OF MAT TYPE IN OPENCV][LIST OF MAT TYPE IN OPENCV]

附錄

數據類型及其取值范圍
數值 具體類型 取值范圍
CV_8U 8 位無符號整數 (0…..255)
CV_8S 8 位符號整數 (-128…..127)
CV_16U 16 位無符號整數 (0……65535)
CV_16S 16 位符號整數 (-32768…..32767)
CV_32S 32 位符號整數 (-2147483648……2147483647)
CV_32F 32 位浮點數 (-FLT_MAX ………FLT_MAX,INF,NAN)
CV_64F 64 位浮點數 (-DBL_MAX ……….DBL_MAX,INF,NAN)
Vec 類的定義
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;


[LIST OF MAT TYPE IN OPENCV]: http://ninghang.blogspot.jp/2012/11/list-of-mat-type-in-opencv.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容