我对OpenCV中type()
的Mat
对象方法感到困惑。
如果我有以下几行:
mat = imread("C:\someimage.jpg");
type = mat.type();
和type = 16
。我如何找出垫矩阵的类型?
我试图在手册或几本徒劳的书中找到答案。
depth()
代码,这对于来说要困难得多type()
。
我对OpenCV中type()
的Mat
对象方法感到困惑。
如果我有以下几行:
mat = imread("C:\someimage.jpg");
type = mat.type();
和type = 16
。我如何找出垫矩阵的类型?
我试图在手册或几本徒劳的书中找到答案。
depth()
代码,这对于来说要困难得多type()
。
Answers:
这是一个方便的函数,可用于在运行时帮助您识别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()
。此功能只是从位值都存储在相同值中的两个值的组合中获得易于理解的解释的便捷方法。
depth
和,chans
您可以分别使用宏CV_MAT_DEPTH(type)
和CV_MAT_CN(type)
。它们的类型也应该是int
,这将允许您使用to_string(chans)
而不是chans+'0'
。
为了进行调试,以防在调试器中查找原始的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)。
在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
)-因此它不会告诉您任何有关原始文件的信息。
types_c.h
位于核心模块中很有用,例如,如果您将OpenCV直接安装在C驱动器上的文件夹opencv_2.4.11中,则头文件将位于C:\ opencv_2.4.11 \ build \ include \ opencv2 \ core \ types_c .h
cv::CV_8U
单击鼠标右键并选择Go to Definition
打开cv::CV_8U
定义的文件,该文件为types_c.h
。
我总是使用此链接查看得到的数字是什么类型type()
:
OPENCV中的MAT TYPE列表
我希望这可以为您提供帮助。
我已经通过@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;
}
其他一些人回答了这个问题,但是我找到了对我来说非常有效的解决方案。
System.out.println(CvType.typeToString(yourMat));
depth()
和channels()
,而不是使用type()
来返回数据类型和通道数之间的复杂混合。