So finden Sie mit Mat :: type () in OpenCV heraus, welcher Typ eines Mat-Objekts ist

118

Ich bin irgendwie verwirrt mit type()der MatObjektmethode in OpenCV.
Wenn ich folgende Zeilen habe:

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

und type = 16. Wie finde ich heraus, um welche Art von Mattenmatrix es sich handelt?
Ich habe vergeblich versucht, die Antwort in seinem Handbuch oder in ein paar Büchern zu finden.

Tae-Sung Shin
quelle
6
Bevorzugen Sie für die menschliche Interpretation die Verwendung von depth()und channels()anstelle der Verwendung, type()die eine komplexe Mischung zwischen Datentyp und Anzahl der Kanäle zurückgibt.
BConic
@Aldur, Der Rückgabewert von depth () ist immer noch nicht lesbar. Sie müssen es mit den Definitionen vergleichen: CV_8U, CV_8S, etc ...
Octopus
1
@octopus sicher, aber mit ein wenig Übung können Sie die gängigen depth()Codes lernen , was weitaus schwieriger ist type().
BConic
Bitte beachten Sie, dass depth () den CV-Aufzählungswert für diesen Typ zurückgibt (für Anfänger etwas irreführend). Wenn Sie die Größe einer in der Mat gespeicherten Zahl in Bytes benötigen, verwenden Sie Mat.elemSize1 (). Wenn Sie den Typ zur Laufzeit benötigen, z. B. innerhalb einer Funktion, in der verschiedene Typen übergeben werden, finden Sie hier einen Vorlagentyp TypeDepth <> (möglicherweise sollten wir ihn umbenennen, da er keine CV-Tiefe hat): stackoverflow.com/questions/ 15245262 /…
Karsten

Antworten:

196

Hier ist eine praktische Funktion, mit der Sie Ihre opencv-Matrizen zur Laufzeit identifizieren können. Ich finde es zumindest zum Debuggen nützlich.

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

Wenn Mes sich um eine Var-Typ handelt Mat, können Sie sie folgendermaßen aufrufen:

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

Gibt Daten aus wie:

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

Es ist erwähnenswert, dass es auch Matrix-Methoden Mat::depth()und gibt Mat::channels(). Diese Funktion ist nur eine praktische Möglichkeit, aus der Kombination dieser beiden Werte, deren Bits alle im selben Wert gespeichert sind, eine lesbare Interpretation zu erhalten.

Tintenfisch
quelle
7
Vielen Dank für diese Funktion, Sie haben mein Leben viel einfacher gemacht! Enttäuschend, dass eine solche Funktion noch nicht in opencv thow integriert ist.
Milania
1
Ich habe Gist mit der Methode aus der Antwort in Objective-C erstellt. Genießen!
Tomasz Bąk
1
Eine Übersicht über die Typen finden Sie auch in dieser Antwort (5 = 32F, 6 = 64F): stackoverflow.com/questions/12335663/…
Lenar Hoyt
Kann jemand dies tatsächlich zu einer praktischen Funktion für openCV machen?
Sharan Duggirala
1
Um depthund chansman kann den Makros verwendet CV_MAT_DEPTH(type)und CV_MAT_CN(type)ist. Ihr Typ sollte auch sein int, was Ihnen erlauben würde, to_string(chans)anstelle von zu verwenden chans+'0'.
John
150

Für Debugging-Zwecke, falls Sie einen rohen Mat :: -Typ in einem Debugger nachschlagen möchten:

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

Wenn beispielsweise type = 30 ist, lautet der OpenCV-Datentyp CV_64FC4. Wenn Typ = 50, ist der OpenCV-Datentyp CV_16UC (7).

Kevin Johnsrude
quelle
6
Was bedeutet das C (X)?
Alanwsx
5
^ Die Anzahl der Kanäle in der Matrix
Arijit
3
^ Was ist dann der Unterschied zwischen C5 und C (5)?
Mateen Ulhaq
1
Es gibt keinen Unterschied.
Kevin Johnsrude
1
Vielen Dank. Dies sollte die beste Antwort sein
Regomodo
32

Im OpenCV-Header " types_c.h " gibt es eine Reihe von Definitionen , die diese generieren. Das Format lautet CV_bits{U|S|F}C<number_of_channels>
also CV_8UC38-Bit-Zeichen ohne Vorzeichen, 3 Farbkanäle - jeder dieser Namen wird einer beliebigen Ganzzahl mit den Makros in dieser Datei zugeordnet.

Bearbeiten: Siehe " types_c.h " zum Beispiel:

#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

So CV_8UC3 = 16 aber sie sollen nicht diese Nummer verwenden, nur überprüfen , type() == CV_8UC3wenn Sie wissen müssen, welche Art eine interne OpenCV Array ist.
Denken Sie daran, dass OpenCV das JPEG in BGR konvertiert (oder Graustufen, wenn Sie '0' übergeben imread) - es sagt Ihnen also nichts über die Originaldatei aus.

Martin Beckett
quelle
Es ist nützlich zu wissen, dass types_c.hsich das im Kernmodul befindet, z. B. wenn Sie OpenCV direkt auf dem Laufwerk C in einem Ordner opencv_2.4.11 installiert haben , befindet sich die Header-Datei unter C: \ opencv_2.4.11 \ build \ include \ opencv2 \ core \ types_c .h
user3731622
Wenn Sie eine IDE verwenden, die "Go Do Definition" -Funktionalität wie Visual Studio enthält, können Sie mit der cv::CV_8Urechten Maustaste klicken und auswählen Go to Definition, um die Datei zu öffnen, in der die cv::CV_8UDefinition definiert ist types_c.h.
user3731622
12

Ich benutze immer diesen Link, um zu sehen, mit welchem ​​Typ ich die Nummer bekomme type():
LISTE DES MATTYPEN IN OPENCV
Ich hoffe, das kann Ihnen helfen.

Angie Quijano
quelle
8

Ich habe der Funktion aus der Antwort von @Octopus eine gewisse Benutzerfreundlichkeit für Debugging-Zwecke hinzugefügt.

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
quelle
6

Dies wurde von einigen anderen beantwortet, aber ich fand eine Lösung, die für mich wirklich gut funktionierte.

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