Come scoprire che tipo di un oggetto Mat è con Mat :: type () in OpenCV


118

Sono un po 'confuso con il type()metodo Matdell'oggetto in OpenCV.
Se ho le seguenti righe:

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

e type = 16. Come faccio a sapere che tipo di matrice è ?.
Ho cercato invano di trovare la risposta nel suo manuale o in un paio di libri.


6
Per l'interpretazione umana, preferisci l'uso di depth()e channels(), invece di usare type()che restituisce un mix complesso tra tipo di dati e numero di canali.
BConic

@ Aldur, il valore restituito da depth () non è ancora leggibile dall'uomo. devi confrontarlo con le definizioni: CV_8U, CV_8S, ecc ...
Octopus

1
@octopus certo, ma con un po 'di pratica puoi imparare i depth()codici comuni , il che è molto più difficile type().
BConic

Si noti che depth () restituisce il valore di enumerazione CV per questo tipo (un po 'fuorviante per i principianti). Se è necessaria la dimensione di un numero memorizzato in Mat in byte, utilizzare Mat.elemSize1 (). Se hai bisogno del tipo in fase di runtime, ad esempio all'interno di una funzione in cui vengono passati diversi tipi, puoi trovare un tipo di modello TypeDepth <> (forse dovremmo rinominarlo poiché non è una profondità CV) qui: stackoverflow.com/questions/ 15245262 /…
karsten,

Risposte:


196

Ecco una comoda funzione che puoi usare per aiutare a identificare le tue matrici opencv in fase di esecuzione. Lo trovo utile per il debug, almeno.

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

Se Mè una variabile di tipo Matpuoi chiamarla così:

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

Produrrà dati come:

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

Vale la pena notare che esistono anche metodi Matrix Mat::depth()e Mat::channels(). Questa funzione è solo un modo pratico per ottenere un'interpretazione leggibile dall'uomo dalla combinazione di quei due valori i cui bit sono tutti memorizzati nello stesso valore.


7
Grazie per questa funzione, mi hai reso la vita molto più facile! Deludente che una tale funzione non sia già integrata in opencv thow.
Milania

1
Ho creato Gist con il metodo dalla risposta in Objective-C. Godere!
Tomasz Bąk

1
Per una panoramica dei tipi vedere anche questa risposta (5 = 32F, 6 = 64F): stackoverflow.com/questions/12335663/…
Lenar Hoyt

Qualcuno può davvero trasformarlo in una comoda funzione per openCV?
Sharan Duggirala

1
Per ottenere depthe chanspotresti usare le macro CV_MAT_DEPTH(type)e CV_MAT_CN(type), rispettivamente. Anche il loro tipo dovrebbe essere int, che ti consentirebbe di usare al to_string(chans)posto di chans+'0'.
Giovanni

151

Per scopi di debug nel caso in cui desideri cercare un Mat :: digita un 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 |
+--------+----+----+----+----+------+------+------+------+

Quindi, ad esempio, se type = 30, il tipo di dati OpenCV è CV_64FC4. Se type = 50, il tipo di dati OpenCV è CV_16UC (7).


6
Cosa significa la C (X)?
alanwsx

5
^ Il numero di canali nella matrice
Arijit

3
^ Qual è la differenza tra C5 e C (5), allora?
Mateen Ulhaq

1
Non c'è differenza.
Kevin Johnsrude

1
Grazie. Questa dovrebbe essere la risposta migliore
regomodo

32

Nell'intestazione OpenCV " types_c.h " ci sono una serie di definisce che li generano, il formato è CV_bits{U|S|F}C<number_of_channels>
Quindi per esempio CV_8UC3significa caratteri senza segno a 8 bit, 3 canali di colore - ognuno di questi nomi mappato su un numero intero arbitrario con le macro in quel file.

Modifica: vedi " types_c.h " per esempio:

#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

Quindi, CV_8UC3 = 16 ma non dovresti usare questo numero, controlla solo type() == CV_8UC3se hai bisogno di sapere che tipo è un array OpenCV interno.
Ricorda che OpenCV convertirà il jpeg in BGR (o scala di grigi se passi "0" a imread), quindi non ti dice nulla sul file originale.


È utile sapere che types_c.hsi trova nel modulo principale, ad esempio se hai OpenCV installato direttamente sull'unità C in una cartella opencv_2.4.11 il file di intestazione sarebbe in C: \ opencv_2.4.11 \ build \ include \ opencv2 \ core \ types_c .h
user3731622

Inoltre, se stai utilizzando un IDE che include la funzionalità "go do definition" come Visual Studio, puoi digitare il cv::CV_8Utasto destro del mouse e selezionare Go to Definitionper aprire il file in cui cv::CV_8Uè definito che è types_c.h.
user3731622


8

Ho aggiunto un po 'di usabilità alla funzione dalla risposta di @Octopus, per scopi di debug.

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

Qualcuno ha risposto a questa domanda, ma ho trovato una soluzione che ha funzionato molto bene per me.

System.out.println(CvType.typeToString(yourMat));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.