Cara mengetahui jenis objek Mat dengan Mat :: type () di OpenCV

118

Saya agak bingung dengan type()metode Matobjek di OpenCV.
Jika saya memiliki baris berikut:

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

dan type = 16. Bagaimana cara mengetahui jenis matriks mat ?.
Saya mencoba menemukan jawabannya di manualnya atau di beberapa buku dengan sia-sia.

Tae-Sung Shin
sumber
6
Untuk interpretasi manusia, lebih suka penggunaan depth()dan channels(), daripada menggunakan type()yang mengembalikan campuran kompleks antara tipe data dan jumlah saluran.
BConic
@Aldur, Nilai kembalian dari depth () masih belum bisa dibaca manusia. Anda harus membandingkannya dengan definisi: CV_8U, CV_8S, dll ...
Octopus
1
@octopus tentu saja tetapi dengan sedikit latihan Anda dapat mempelajari depth()kode - kode umum , yang jauh lebih sulit untuk itu type().
BConic
Harap dicatat bahwa depth () mengembalikan nilai enum CV untuk tipe ini (agak menyesatkan bagi pemula). Jika Anda membutuhkan ukuran satu nomor yang disimpan dalam Mat dalam byte, gunakan Mat.elemSize1 (). Jika Anda memerlukan tipe saat runtime, misalnya dalam fungsi di mana tipe berbeda diteruskan ke dalamnya, Anda dapat menemukan tipe template TypeDepth <> (mungkin kita harus mengganti namanya karena tidak ada kedalaman CV) di sini: stackoverflow.com/questions/ 15245262 /…
karsten

Jawaban:

196

Berikut adalah fungsi praktis yang dapat Anda gunakan untuk membantu mengidentifikasi matriks terbuka Anda pada waktu proses. Saya merasa berguna untuk debugging, setidaknya.

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;
}

Jika Msebuah var tipe MatAnda dapat menyebutnya seperti ini:

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

Akan mengeluarkan data seperti:

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

Perlu dicatat bahwa ada juga metode Matrix Mat::depth()dan Mat::channels(). Fungsi ini hanyalah cara praktis untuk mendapatkan interpretasi yang dapat dibaca manusia dari kombinasi dua nilai yang semua bitnya disimpan dalam nilai yang sama.

Gurita
sumber
7
Terima kasih untuk fungsi ini, Anda membuat hidup saya jauh lebih mudah! Mengecewakan bahwa fungsi seperti itu belum terintegrasi dalam sistem terbuka.
Milania
1
Saya telah membuat Gist dengan metode dari jawaban di Objective-C. Nikmati!
Tomasz Bąk
1
Untuk gambaran umum tentang tipe, lihat juga jawaban ini (5 = 32F, 6 = 64F): stackoverflow.com/questions/12335663/…
Lenar Hoyt
Bisakah seseorang benar-benar membuat ini menjadi fungsi praktis untuk openCV?
Sharan Duggirala
1
Untuk mendapatkan depthdan chansAnda bisa menggunakan makro CV_MAT_DEPTH(type)dan CV_MAT_CN(type), masing-masing. Jenisnya juga harus int, yang memungkinkan Anda untuk menggunakan, to_string(chans)bukan chans+'0'.
Yohanes
151

Untuk keperluan debugging jika Anda ingin mencari Mat :: type mentah di debugger:

+--------+----+----+----+----+------+------+------+------+
|        | 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 |
+--------+----+----+----+----+------+------+------+------+

Jadi misalnya jika type = 30 maka tipe data OpenCV adalah CV_64FC4. Jika tipe = 50 maka tipe data OpenCV adalah CV_16UC (7).

Kevin Johnsrude
sumber
6
Apa artinya C (X)?
alanwsx
5
^ Jumlah saluran dalam matriks
Arijit
3
^ Lalu, apa perbedaan antara C5 dan C (5)?
Mateen Ulhaq
1
Tidak ada perbedaan.
Kevin Johnsrude
1
Terima kasih. Ini harus menjadi jawaban teratas
regomodo
32

Dalam OpenCV header " types_c.h " ada satu set definisi yang menghasilkan ini, formatnya adalah CV_bits{U|S|F}C<number_of_channels>
Jadi misalnya CV_8UC3berarti karakter unsigned 8 bit, 3 saluran warna - masing-masing nama ini dipetakan ke integer sewenang-wenang dengan makro di file itu.

Edit: Lihat " types_c.h " misalnya:

#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

Jadi, CV_8UC3 = 16 tetapi Anda tidak seharusnya menggunakan nomor ini, cukup periksa type() == CV_8UC3apakah Anda perlu tahu apa jenis array OpenCV internal itu.
Ingat OpenCV akan mengonversi jpeg menjadi BGR (atau skala abu-abu jika Anda meneruskan '0' ke imread) - jadi itu tidak memberi tahu Anda apa pun tentang file aslinya.

Martin Beckett
sumber
Ini berguna untuk mengetahui bahwa types_c.hterletak di modul inti, misalnya jika Anda menginstal OpenCV langsung di drive C di folder opencv_2.4.11 file header akan berada di C: \ opencv_2.4.11 \ build \ include \ opencv2 \ core \ types_c .h
user3731622
Juga, jika Anda menggunakan IDE yang menyertakan fungsionalitas "go do definition" seperti Visual Studio, Anda dapat mengetikkan cv::CV_8Uklik kanan dan memilih Go to Definitionuntuk membuka file di mana cv::CV_8Uditentukan types_c.h.
user3731622
12

Saya selalu menggunakan link ini untuk melihat jenis nomor yang saya dapatkan dengan type():
DAFTAR JENIS MAT DI OPENCV
Saya harap ini dapat membantu Anda.

Angie Quijano
sumber
8

Saya telah menambahkan beberapa kegunaan ke fungsi dari jawaban oleh @Octopus, untuk tujuan debugging.

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;

}
shahar_m
sumber
6

Ini dijawab oleh beberapa orang lain tetapi saya menemukan solusi yang bekerja sangat baik untuk saya.

System.out.println(CvType.typeToString(yourMat));
ProgrammingCuber
sumber