web-dev-qa-db-fra.com

Comment savoir quel type d'objet Mat est avec Mat :: type () dans OpenCV

Je suis un peu confus avec la méthode type() de l'objet Mat dans OpenCV.
Si j'ai les lignes suivantes:

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

et type = 16. Comment puis-je savoir quel type de matrice est mat.
J'ai essayé de trouver la réponse dans son manuel ou dans quelques livres en vain.

100
Tae-Sung Shin

Voici une fonction pratique que vous pouvez utiliser pour vous aider à identifier vos matrices ouvertes à l’exécution. Je trouve cela utile pour le débogage, au moins.

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

Si M est une var de type Mat, vous pouvez l'appeler comme suit:

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

Est-ce que des données telles que:

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

Il est à noter qu'il existe également des méthodes matricielles Mat::depth() et Mat::channels(). Cette fonction est juste un moyen pratique d'obtenir une interprétation lisible par l'homme à partir de la combinaison de ces deux valeurs dont les bits sont tous stockés dans la même valeur.

163
Octopus

À des fins de débogage, au cas où vous souhaiteriez rechercher un Mat :: type brut dans un débogueur:

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

Ainsi, par exemple, si type = 30, le type de données OpenCV est CV_64FC4. Si type = 50, le type de données OpenCV est CV_16UC (7).

106
Kevin Johnsrude

Dans l'en-tête OpenCV " types_c.h ", il existe un ensemble de définitions qui les génèrent, le format est CV_bits{U|S|F}C<number_of_channels>
Ainsi, par exemple CV_8UC3 Signifie 8 caractères non signés, 3 canaux de couleur - chacun de ces noms mappe sur un entier arbitraire avec les macros de ce fichier.

Edit: Voir " types_c.h " par exemple:

#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

Donc, CV_8UC3 = 16 Mais vous n'êtes pas censé utiliser ce nombre, cochez simplement type() == CV_8UC3 si vous avez besoin de savoir quel type de tableau OpenCV interne est.
N'oubliez pas qu'OpenCV convertira le fichier jpeg en BGR (ou en échelle de gris si vous passez "0" à imread) - de sorte qu'il ne vous en dit rien sur le fichier d'origine.

32
Martin Beckett

J'utilise toujours ce lien pour voir quel type correspond au numéro obtenu avec type():
LISTE DU TYPE DE TAPIS DANS OPENCV
J'espère que ceci peut vous aider.

11
Angie Quijano

J'ai ajouté un peu de convivialité à la fonction à partir de la réponse de @Octopus, à des fins de débogage.

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;

}
7
shahar_m

Quelques autres ont répondu à cela, mais j'ai trouvé une solution qui fonctionnait vraiment bien pour moi.

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