How to find out what type of a Mat object is with Mat::type() in OpenCV?
Asked Answered
S

6

158

I am kind of confused with type() method of Mat object in OpenCV.
If I have following lines:

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

and type = 16, how do I find out what type of mat matrix is?.
I tried to find the answer in its manual and in a couple of books in vain.

Shangrila answered 16/4, 2012 at 0:51 Comment(4)
For human interpretation, prefer the use of depth() and channels(), instead of using type() which returns a complex mix between datatype and number of channels.Schreck
@Aldur, The return value of depth() still isn't human readable. you have to compare it to the defines: CV_8U, CV_8S, etc...Gomphosis
@octopus sure but with a bit of practice you can learn the common depth() codes, which is far harder for type().Schreck
Please note that depth() returns the CV enum value for this type (a bit misleading to beginners). If you need size of one number stored in the Mat in bytes use Mat.elemSize1(). If you need the type at runtime, e.g. within a function where different types are passed into it, you can find a template type TypeDepth<> (maybe we should rename it since it is no CV depth) here: #15245762Shaer
G
265

Here is a handy function you can use to help with identifying your opencv matrices at runtime. I find it useful for debugging, at least.

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;
}

If M is a var of type Mat you can call it like so:

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

Will output data such as:

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

Its worth noting that there are also Matrix methods Mat::depth() and Mat::channels(). This function is just a handy way of getting a human readable interpretation from the combination of those two values whose bits are all stored in the same value.

Gomphosis answered 23/7, 2013 at 20:40 Comment(7)
I've created Gist with method from the answer in Objective-C. Enjoy!Comstockery
For an overview of the types also see this answer (5=32F, 6=64F): #12336163Yonder
Can someone actually make this into a handy function for openCV?Ramsdell
To get depth and chans you could use the macros CV_MAT_DEPTH(type) and CV_MAT_CN(type), respectively. Their type should also be int, which would allow you to use to_string(chans) instead of chans+'0'.Claimant
@Claimant On the other hand, to_string is slightly slower if it's known in advance that the number is exactly 1-digit.Cabaret
@Cabaret I would still use to_string here, since it is more explicit. Usually getting the type of an image should not be relevant for the performance in comparison to the operations you do on an image. Yet a good comment and it might be useful to remember in general, thanks.Claimant
Mats can have upto 512 channels. this code will struggle beyond 9 channels. since that's very unusual, it's something to fix but not an immediate problem.Poland
N
275

For debugging purposes in case you want to look up a raw Mat::type in a debugger:

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

So for example, if type = 30 then OpenCV data type is CV_64FC4. If type = 50 then the OpenCV data type is CV_16UC(7).

Nutshell answered 29/9, 2016 at 22:11 Comment(6)
What does the C(X) mean?Greenling
^The number of channels in the matrixLongueur
^ What's the difference between C5 and C(5), then?Decompress
There is no difference.Nutshell
@MateenUlhaq just a small note: You can create images(Mat Objects) of upto 4-bit channels without the bracket (in the type parameter) but creating images of >=5 channels will return an error. Example: Mat img(23, 53, CV_64FC(5)) is valid but Mat img(23, 53, CV_64FC5) is invalid.Angie
@MateenUlhaq Constants for ones with more than 4 channels have to be expressed with a C++ macro. Hence the parentheses.Crabber
G
265

Here is a handy function you can use to help with identifying your opencv matrices at runtime. I find it useful for debugging, at least.

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;
}

If M is a var of type Mat you can call it like so:

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

Will output data such as:

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

Its worth noting that there are also Matrix methods Mat::depth() and Mat::channels(). This function is just a handy way of getting a human readable interpretation from the combination of those two values whose bits are all stored in the same value.

Gomphosis answered 23/7, 2013 at 20:40 Comment(7)
I've created Gist with method from the answer in Objective-C. Enjoy!Comstockery
For an overview of the types also see this answer (5=32F, 6=64F): #12336163Yonder
Can someone actually make this into a handy function for openCV?Ramsdell
To get depth and chans you could use the macros CV_MAT_DEPTH(type) and CV_MAT_CN(type), respectively. Their type should also be int, which would allow you to use to_string(chans) instead of chans+'0'.Claimant
@Claimant On the other hand, to_string is slightly slower if it's known in advance that the number is exactly 1-digit.Cabaret
@Cabaret I would still use to_string here, since it is more explicit. Usually getting the type of an image should not be relevant for the performance in comparison to the operations you do on an image. Yet a good comment and it might be useful to remember in general, thanks.Claimant
Mats can have upto 512 channels. this code will struggle beyond 9 channels. since that's very unusual, it's something to fix but not an immediate problem.Poland
R
37

In OpenCV header "types_c.h" there are a set of defines which generate these, the format is CV_bits{U|S|F}C<number_of_channels>
So for example CV_8UC3 means 8 bit unsigned chars, 3 colour channels - each of these names map onto an arbitrary integer with the macros in that file.

Edit: See "types_c.h" for example:

#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

So CV_8UC3 = 16 but you aren't supposed to use this number, just check type() == CV_8UC3 if you need to know what type an internal OpenCV array is.
Remember OpenCV will convert the jpeg into BGR (or grey scale if you pass '0' to imread) - so it doesn't tell you anything about the original file.

Racer answered 16/4, 2012 at 3:50 Comment(2)
It's useful to know that types_c.h is located in the core module, e.g. if you have OpenCV installed directly on C drive in a folder opencv_2.4.11 the header file would be at C:\opencv_2.4.11\build\include\opencv2\core\types_c.hAmelia
Also, if you're using an IDE which includes "go do definition" functionality like Visual Studio you can type cv::CV_8U right-click and select Go to Definition to open the file where cv::CV_8U is defined which is types_c.h.Amelia
B
19

This was answered by a few others but I found a solution that worked really well for me.

System.out.println(CvType.typeToString(yourMat.type()));
Bakke answered 15/8, 2017 at 19:21 Comment(2)
C++: cv::typeToStringFellowman
Note: This API is added since 3.4.2 for 3.x branch. The 4.x branch has this API since 4.0.0.Mccloskey
L
16

I've added some usability to the function from the answer by @Octopus, for debugging purposes.

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;
    
}
Lucchesi answered 4/4, 2017 at 19:7 Comment(1)
Mats can have upto 512 channels. this code will struggle beyond 9 channels. since that's very unusual, it's something to fix but not an immediate problem.Poland
E
8

Base on @Matt Edding's comment (Thanks Mat(T) pun intended ;)):

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

Works like a charm.

Evered answered 23/12, 2021 at 14:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.