24

In the C++ interface to OpenCV, it seems easy enough to check the type of an image. If you have an image cv::Mat img = cv::imread("someImage.xyz"), you just do int theType = img.type().

However, as you would expect, calling img.type() just gives an integer, an not an enum name (e.g. CV_32FC1).

Is there an easy way to print out the enum name (e.g. CV_32FC1) if I know the integer value of the OpenCV enum?

3
  • For those who happen to be familiar with CUDA, the OpenCV function that I'm looking for is sort of like the cudaGetErrorString(int) function in CUDA. Commented Sep 9, 2012 at 0:49
  • 3
    Does this answer your question? How to find out what type of a Mat object is with Mat::type() in OpenCV Commented Aug 14, 2021 at 1:36
  • 1
    voting to close because the other question contains answers that mention cv::typeToString() Commented Jul 2, 2022 at 11:39

3 Answers 3

33

To my knowledge, such a function doesn't exist in OpenCV.

I think you would be better off writing your own function to get those. A lot of switch cases but I guess it does the job. The enumeration can be found here.

EDIT:

This is something you could use to extract the types. I am guessing there could be a more efficient method, but I can't wrap my head around it right now.

std::string getImageType(int number) { // find type int imgTypeInt = number%8; std::string imgTypeString; switch (imgTypeInt) { case 0: imgTypeString = "8U"; break; case 1: imgTypeString = "8S"; break; case 2: imgTypeString = "16U"; break; case 3: imgTypeString = "16S"; break; case 4: imgTypeString = "32S"; break; case 5: imgTypeString = "32F"; break; case 6: imgTypeString = "64F"; break; default: break; } // find channel int channel = (number/8) + 1; std::stringstream type; type<<"CV_"<<imgTypeString<<"C"<<channel; return type.str(); } 
Sign up to request clarification or add additional context in comments.

4 Comments

Good thinking. I followed your suggestion and wrote some code to do this. See my answer below.
Rather than using the ints (which were right at the time you checked them on your particular build) you should use the enums themselves. case 8U: str= "8U" then you're sure to get them right if the enums change in a different build.
Hard coding 8 in the code is not a good idea. See stackoverflow.com/questions/10167534/…
cv::typeToString() makes this obsolete/superfluous
19

Following @Bob's advice, I wrote my own function to solve this problem. Here it is:

// take number image type number (from cv::Mat.type()), get OpenCV's enum string. string getImgType(int imgTypeInt) { int numImgTypes = 35; // 7 base types, with five channel options each (none or C1, ..., C4) int enum_ints[] = {CV_8U, CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4, CV_8S, CV_8SC1, CV_8SC2, CV_8SC3, CV_8SC4, CV_16U, CV_16UC1, CV_16UC2, CV_16UC3, CV_16UC4, CV_16S, CV_16SC1, CV_16SC2, CV_16SC3, CV_16SC4, CV_32S, CV_32SC1, CV_32SC2, CV_32SC3, CV_32SC4, CV_32F, CV_32FC1, CV_32FC2, CV_32FC3, CV_32FC4, CV_64F, CV_64FC1, CV_64FC2, CV_64FC3, CV_64FC4}; string enum_strings[] = {"CV_8U", "CV_8UC1", "CV_8UC2", "CV_8UC3", "CV_8UC4", "CV_8S", "CV_8SC1", "CV_8SC2", "CV_8SC3", "CV_8SC4", "CV_16U", "CV_16UC1", "CV_16UC2", "CV_16UC3", "CV_16UC4", "CV_16S", "CV_16SC1", "CV_16SC2", "CV_16SC3", "CV_16SC4", "CV_32S", "CV_32SC1", "CV_32SC2", "CV_32SC3", "CV_32SC4", "CV_32F", "CV_32FC1", "CV_32FC2", "CV_32FC3", "CV_32FC4", "CV_64F", "CV_64FC1", "CV_64FC2", "CV_64FC3", "CV_64FC4"}; for(int i=0; i<numImgTypes; i++) { if(imgTypeInt == enum_ints[i]) return enum_strings[i]; } return "unknown image type"; } 

Did I forget to include any OpenCV image types in my lookup table?

5 Comments

You have to notice two things though. First, there is no case where you have zero channels, there is always at least 1 channel, which actually means that CV_8U = CV_8UC1 etc. And second, you could have up to CV_CN_MAX channels which according to the 2.4.2 documentation is set to 512, so you are limiting yourself to 4 channels this way. I wrote something, see my edit, just make sure to test it cause I didn't compile it.
@Bob are you sure that the enums for 5 to 512 pixels are implemented? The compiler says that CV_8UC5 is not defined.
They are not #defined, but they are derived using CV_MAKETYPE, e.g.CV_MAKETYPE(CV_32F, 5); Of course if you don't plan using so many channels, you can use your function, just remove the CV_8U etc cause they return the same result as CV_8UC1 etc
@Bob Ah, that makes sense. I'm trying to understand all the subtleties of the cv::Mat data structure, so I'm glad you pointed this out.
cv::typeToString() makes this obsolete/superfluous
-1

I'm very late, but a std::map<int, std::string> can be cool :)

static const std::map<int, std::string> myMap = { {CV_8U , "CV_8U"}, {CV_8S , "CV_8S"}, {CV_16U, "CV_16U"}, {CV_16S, "CV_16S"}, {CV_32S, "CV_32S"}, {CV_32F, "CV_32F"}, {CV_64F, "CV_64F"}, }; 

Then just std::strcat the "C" and the number of channels if needed.

 std::stringstream ss; ss<<myMap.at(your_type)<<"C"<<channels; 

2 Comments

cv::typeToString() makes this obsolete/superfluous
true, that should be the answer

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.