如何在OpenCV中使用Mat :: type()找出Mat对象的类型


118

我对OpenCV中type()Mat对象方法感到困惑。
如果我有以下几行:

mat = imread("C:\someimage.jpg");
type = mat.type();

type = 16。我如何找出垫矩阵的类型?
我试图在手册或几本徒劳的书中找到答案。


6
对于人工解释,更喜欢使用depth()channels(),而不是使用type()来返回数据类型和通道数之间的复杂混合。
BConic

@ Aldur,depth()的返回值仍然不是人类可读的。您必须将其与以下定义进行比较:CV_8U,CV_8S等...
Octopus

1
@octopus可以肯定,但要稍作练习,您可以学习通用depth()代码,这对于来说要困难得多type()
BConic

请注意,depth()返回此类型的CV枚举值(这对初学者有些误导)。如果您需要以字节为单位存储在Mat中的一个数字的大小,请使用Mat.elemSize1()。如果您在运行时需要类型,例如在传递不同类型的函数中,则可以在此处找到模板类型TypeDepth <>(也许由于我们没有CV深度,所以我们应该对其进行重命名):stackoverflow.com/questions/ 15245262 /…
karsten

Answers:


196

这是一个方便的函数,可用于在运行时帮助您识别opencv矩阵。我发现它至少对调试有用。

string type2str(int type) {
  string r;

  uchar depth = type & CV_MAT_DEPTH_MASK;
  uchar chans = 1 + (type >> CV_CN_SHIFT);

  switch ( depth ) {
    case CV_8U:  r = "8U"; break;
    case CV_8S:  r = "8S"; break;
    case CV_16U: r = "16U"; break;
    case CV_16S: r = "16S"; break;
    case CV_32S: r = "32S"; break;
    case CV_32F: r = "32F"; break;
    case CV_64F: r = "64F"; break;
    default:     r = "User"; break;
  }

  r += "C";
  r += (chans+'0');

  return r;
}

如果M是var类型Mat,则可以这样称呼它:

string ty =  type2str( M.type() );
printf("Matrix: %s %dx%d \n", ty.c_str(), M.cols, M.rows );

将输出数据,例如:

Matrix: 8UC3 640x480 
Matrix: 64FC1 3x2 

值得注意的是,还有Matrix方法Mat::depth()Mat::channels()。此功能只是从位值都存储在相同值中的两个值的组合中获得易于理解的解释的便捷方法。


7
感谢使用此功能,您使我的生活更加轻松!令人失望的是,opencv thow中尚未集成这样的功能。
Milania 2014年

1
我已经从Objective-C的答案中创建了方法。请享用!
TomaszBąk2014年

1
对于类型的一个概述也看到此答案(5 = 32F,6 = 64F):stackoverflow.com/questions/12335663/...
Lenar霍伊特

有人真的可以将它变成openCV的便捷功能吗?
莎朗·杜吉拉拉

1
要获取depth和,chans您可以分别使用宏CV_MAT_DEPTH(type)CV_MAT_CN(type)。它们的类型也应该是int,这将允许您使用to_string(chans)而不是chans+'0'
约翰·

151

为了进行调试,以防在调试器中查找原始的Mat :: type:

+--------+----+----+----+----+------+------+------+------+
|        | C1 | C2 | C3 | C4 | C(5) | C(6) | C(7) | C(8) |
+--------+----+----+----+----+------+------+------+------+
| CV_8U  |  0 |  8 | 16 | 24 |   32 |   40 |   48 |   56 |
| CV_8S  |  1 |  9 | 17 | 25 |   33 |   41 |   49 |   57 |
| CV_16U |  2 | 10 | 18 | 26 |   34 |   42 |   50 |   58 |
| CV_16S |  3 | 11 | 19 | 27 |   35 |   43 |   51 |   59 |
| CV_32S |  4 | 12 | 20 | 28 |   36 |   44 |   52 |   60 |
| CV_32F |  5 | 13 | 21 | 29 |   37 |   45 |   53 |   61 |
| CV_64F |  6 | 14 | 22 | 30 |   38 |   46 |   54 |   62 |
+--------+----+----+----+----+------+------+------+------+

因此,例如,如果type = 30,则OpenCV数据类型为CV_64FC4。如果type = 50,则OpenCV数据类型为CV_16UC(7)。


6
C(X)是什么意思?
alanwsx

5
^矩阵中的通道数
Arijit

3
^那么C5和C(5)有什么区别?
Mateen Ulhaq '17

1
没有区别。
凯文·约翰斯鲁德

1
谢谢。这应该是最好的答案
regomodo

32

在OpenCV标头“ types_c.h ”中,有一组定义会生成这些定义,格式为CV_bits{U|S|F}C<number_of_channels>
,例如CV_8UC3表示8位无符号字符,3个颜色通道-这些名称中的每一个都映射到该文件中带有宏的任意整数。

编辑:例如,请参见“ types_c.h ”:

#define CV_8UC3 CV_MAKETYPE(CV_8U,3)
#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))

eg.
depth = CV_8U = 0
cn = 3
CV_CN_SHIFT = 3

CV_MAT_DEPTH(0) = 0
(((cn)-1) << CV_CN_SHIFT) = (3-1) << 3 = 2<<3 = 16

因此,CV_8UC3 = 16 但是您不应该使用此数字,只需检查type() == CV_8UC3是否需要知道内部OpenCV数组的类型即可。
请记住,OpenCV会将jpeg转换为BGR(如果将'0'传递给,则为灰度imread)-因此它不会告诉您任何有关原始文件的信息。


知道它types_c.h位于核心模块中很有用,例如,如果您将OpenCV直接安装在C驱动器上的文件夹opencv_2.4.11中,则头文件将位于C:\ opencv_2.4.11 \ build \ include \ opencv2 \ core \ types_c .h
user3731622

另外,如果您使用的IDE包含Visual Studio等“执行定义”功能,则可以cv::CV_8U单击鼠标右键并选择Go to Definition打开cv::CV_8U定义的文件,该文件为types_c.h
user3731622


8

我已经通过@Octopus的答案为函数添加了一些可用性,以用于调试。

void MatType( Mat inputMat )
{
    int inttype = inputMat.type();

    string r, a;
    uchar depth = inttype & CV_MAT_DEPTH_MASK;
    uchar chans = 1 + (inttype >> CV_CN_SHIFT);
    switch ( depth ) {
        case CV_8U:  r = "8U";   a = "Mat.at<uchar>(y,x)"; break;  
        case CV_8S:  r = "8S";   a = "Mat.at<schar>(y,x)"; break;  
        case CV_16U: r = "16U";  a = "Mat.at<ushort>(y,x)"; break; 
        case CV_16S: r = "16S";  a = "Mat.at<short>(y,x)"; break; 
        case CV_32S: r = "32S";  a = "Mat.at<int>(y,x)"; break; 
        case CV_32F: r = "32F";  a = "Mat.at<float>(y,x)"; break; 
        case CV_64F: r = "64F";  a = "Mat.at<double>(y,x)"; break; 
        default:     r = "User"; a = "Mat.at<UKNOWN>(y,x)"; break; 
    }   
    r += "C";
    r += (chans+'0');
    cout << "Mat is of type " << r << " and should be accessed with " << a << endl;

}

6

其他一些人回答了这个问题,但是我找到了对我来说非常有效的解决方案。

System.out.println(CvType.typeToString(yourMat));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.