142

我对 OpenCVtype()中的对象方法有点困惑。如果我有以下几行:Mat

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

type = 16。我如何找出什么类型的垫矩阵是?
我试图在其手册或几本书中找到答案,但徒劳无功。

4

6 回答 6

245

这是一个方便的函数,您可以使用它来帮助在运行时识别您的 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(). 这个函数只是一种方便的方法,可以从这两个值的组合中获得人类可读的解释,这两个值的位都存储在同一个值中。

于 2013-07-23T20:40:39.207 回答
225

出于调试目的,如果您想在调试器中查找原始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).

于 2016-09-29T22:11:52.900 回答
33

在 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)-因此它不会告诉您有关原始文件的任何信息。

于 2012-04-16T03:50:43.490 回答
14

出于调试目的,我从@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;
    
}
于 2017-04-04T19:07:24.350 回答
11

其他一些人回答了这个问题,但我找到了一个非常适合我的解决方案。

System.out.println(CvType.typeToString(yourMat.type()));
于 2017-08-15T19:21:09.867 回答
1

基于@Matt Edding 的评论(感谢 Mat(T) 双关语;)):

cout << cv::typeToString(inputMat.type()) << endl;

奇迹般有效。

于 2021-12-23T14:36:33.910 回答