OpenCVでMat​​ :: type()を使用してMatオブジェクトのタイプを確認する方法


118

私はOpenCV type()Matオブジェクトのメソッドと混同しています。
次の行がある場合:

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

type = 16。マットマトリックスの種類を確認するにはどうすればよいですか。
そのマニュアルや数冊の本で答えを見つけようとしたが無駄だった。


6
人間の解釈のための使用を好むdepth()channels()、代わりに使用するtype()データ型とチャンネル数との間の複雑なミックスを返します。
BConic

@ Aldur、depth()の戻り値はまだ人間が読める形式ではありません。定義と比較する必要があります:CV_8U、CV_8Sなど...
Octopus

1
@octopusは確かですが、少し練習するだけで、一般的なdepth()コードを学ぶことができますtype()
BConic 2015

depth()はこのタイプのCV列挙値を返すことに注意してください(初心者には少し誤解を招きます)。Matにバイト単位で格納されている1つの数値のサイズが必要な場合は、Mat.elemSize1()を使用します。実行時にタイプが必要な場合、たとえば、異なるタイプが渡される関数内では、テンプレートタイプTypeDepth <>を見つけることができます(CV深度がないため、名前を変更する必要があります)。ここでは、stackoverflow.com
カルステン

回答:


196

これは、実行時に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タイプの変数の場合、次の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()ます。この関数は、ビットがすべて同じ値に格納されている2つの値の組み合わせから人間が読み取れる解釈を取得するための便利な方法です。


7
この機能のおかげで、私の人生がずっと楽になりました!そのような関数がopencvにまだ統合されていないことに失望します。
ミラニア2014

1
Objective-Cの回答からメソッドを使用してGistを作成しました。楽しい!
TomaszBąk14年

1
タイプの概要についても、この答えを見る(5 = 32F、6 = 64F):stackoverflow.com/questions/12335663/...
Lenarホイト

誰かが実際にこれをopenCVの便利な関数にできるか?
Sharan Duggirala 2017年

1
取得するdepthchans、あなたは、マクロを使用することができますCV_MAT_DEPTH(type)し、CV_MAT_CN(type)それぞれ。それらのタイプもである必要がありますint。これにより、のto_string(chans)代わりに使用できますchans+'0'
John

151

デバッガーで生の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)です。


6
C(X)の意味?
alanwsx 2017年

5
^マトリックスのチャネル数
Arijit

3
^では、C5とC(5)の違いは何ですか?
Mateen Ulhaq 2017

1
違いはありません。
Kevin Johnsrude

1
ありがとう。これが一番の答えになるはずです
regomodo

32

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
user3731622

また、Visual Studioのような「定義の実行」機能を含むIDEを使用している場合は、cv::CV_8U右クリックして選択Go to Definitionし、cv::CV_8Uが定義されているファイルを開くことができますtypes_c.h
user3731622


8

デバッグの目的で、@ 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;

}

6

これは他の何人かによって答えられましたが、私には本当にうまくいく解決策を見つけました。

System.out.println(CvType.typeToString(yourMat));
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.