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

我有点搞不懂 OpenCV 中 Mat对象的 type()方法。 < br > 如果我有以下几行:

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

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

198128 次浏览

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

编辑: 参见“ Type _ 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)-所以它不会告诉你任何关于原始文件的信息。

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

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

为了调试的目的,我已经在这个函数的回答中添加了一些可用性。

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;
    

}

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

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

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

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

非常有效。