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

yyhrrdl8  于 2022-11-15  发布在  其他
关注(0)|答案(6)|浏览(174)

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

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

type = 16,如何找出mat矩阵类型?
我试图在它的手册和几本书中找到答案,但都是徒劳的。

vc9ivgsu

vc9ivgsu1#

这里有一个方便的函数,可以用来帮助你在运行时识别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;
}

如果MMat类型的var,则可以这样调用它:

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

将输出数据如:

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

值得注意的是,还有矩阵方法Mat::depth()Mat::channels()。该函数是从这两个值的组合中获得人类可读解释的一种方便的方法,这两个值的位都存储在同一个值中。

zf9nrax1

zf9nrax12#

如果您想在调试器中查找原始Mat::type,则出于调试目的:
| | C1级|C2级|C3级|碳四|丙(五)|丙(六)|丙(7)|丙(八)|
| - -|- -|- -|- -|- -|- -|- -|- -|- -|
| CV_8U|第0页|八个|十六|二十四|三十二|四十|四十八|五十六人|
| CV_8S系列|一个|九个|十七岁|二十五个|三十三个|四十一|四十九|五十七|
| CV_16U型|2个|10个|十八|二十六人|三十四|四十二|五十个|五十八|
| CV_16S系列|三个|十一|十九|二十七人|三十五|四十三|五十一个|五十九|
| CV_32S系列|四个|十二|二十个|二十八人|三十六人|四十四|五十二|六十|
| CV_32F型|五个|十三|二十一个|二十九人|三十七|四十五|五十三个|六十一|
| CV_64F型|六个|十四|二十二个|三十|三十八|四十六|五十四|六十二|
例如,如果type = 30,则OpenCV数据类型为CV_64FC4。如果type = 50,则OpenCV数据类型为CV_16UC(7)

gblwokeq

gblwokeq3#

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

**编辑:**请参阅“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,但你不应该使用这个数字,如果你需要知道内部OpenCV数组是什么类型,只要检查type() == CV_8UC3
请记住,OpenCV会将jpeg转换为BGR(或灰度,如果您将'0'传递给imread)-因此它不会告诉您任何关于原始文件的信息。

ryoqjall

ryoqjall4#

为了调试的目的,我在@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;
    
}
2skhul33

2skhul335#

这是回答了一些其他人,但我发现了一个解决方案,真的很适合我。

System.out.println(CvType.typeToString(yourMat.type()));
nxagd54h

nxagd54h6#

根据@马特·艾丁的评论(谢谢马特(T)双关语;)):
cout << cv::typeToString(inputMat.type()) << endl;
就像个护身符。

相关问题