Jak dowiedzieć się, jaki typ obiektu Mat jest za pomocą Mat :: type () w OpenCV

118

Jestem trochę zmieszany z type()metodą Matobiektu w OpenCV.
Jeśli mam następujące wiersze:

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

i type = 16. Jak mogę się dowiedzieć, jaki jest typ macierzy maty?
Na próżno próbowałem znaleźć odpowiedź w jej podręczniku lub w kilku książkach.

Tae-Sung Shin
źródło
6
W przypadku interpretacji przez człowieka preferuj użycie depth()i channels(), zamiast używania, type()które zwraca złożoną mieszankę między typem danych a liczbą kanałów.
BConic
@Aldur, Wartość zwracana funkcji depth () nadal nie jest czytelna dla człowieka. trzeba to porównać z definicjami: CV_8U, CV_8S, etc ...
Octopus.
1
@octopus oczywiście, ale przy odrobinie praktyki możesz nauczyć się wspólnych depth()kodów, co jest znacznie trudniejsze type().
BConic
Należy pamiętać, że funkcja depth () zwraca wartość wyliczenia CV dla tego typu (trochę mylące dla początkujących). Jeśli potrzebujesz rozmiaru jednej liczby przechowywanej w Mat w bajtach, użyj Mat.elemSize1 (). Jeśli potrzebujesz typu w czasie wykonywania, np. W ramach funkcji, w której przekazywane są różne typy, możesz znaleźć typ szablonu TypeDepth <> (może powinniśmy zmienić jego nazwę, ponieważ nie ma głębokości CV) tutaj: stackoverflow.com/questions/ 15245262 /…
karsten

Odpowiedzi:

196

Oto przydatna funkcja, której możesz użyć, aby pomóc w identyfikacji macierzy opencv w czasie wykonywania. Uważam, że jest to przydatne przynajmniej do debugowania.

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

Jeśli Mjest to typ var Mat, możesz to tak nazwać:

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

Wyświetli dane takie jak:

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

Warto zauważyć, że istnieją również metody Matrix Mat::depth()i Mat::channels(). Ta funkcja jest po prostu wygodnym sposobem uzyskania czytelnej dla człowieka interpretacji z kombinacji tych dwóch wartości, których wszystkie bity są przechowywane w tej samej wartości.

Ośmiornica
źródło
7
Dzięki za tę funkcję znacznie ułatwiłeś mi życie! Rozczarowujące jest to, że taka funkcja nie jest już zintegrowana z opencv thow.
Milania,
1
Stworzyłem Gist metodą z odpowiedzi w Objective-C. Cieszyć się!
Tomasz Bąk,
1
Aby zapoznać się z przeglądem typów, zobacz również tę odpowiedź (5 = 32F, 6 = 64F): stackoverflow.com/questions/12335663/…
Lenar Hoyt
Czy ktoś może faktycznie uczynić z tego przydatną funkcję dla openCV?
Sharan Duggirala
1
Aby uzyskać depthi chansmożesz użyć odpowiednio makr CV_MAT_DEPTH(type)i CV_MAT_CN(type). Powinien być również ich typ int, który pozwoliłby na użycie to_string(chans)zamiast chans+'0'.
John
151

Do celów debugowania w przypadku, gdy chcesz wyszukać surowy plik Mat :: wpisz w debugerze:

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

Na przykład, jeśli typ = 30, typ danych OpenCV to CV_64FC4. Jeśli typ = 50, typ danych OpenCV to CV_16UC (7).

Kevin Johnsrude
źródło
6
Co oznacza C (X)?
alanwsx
5
^ Liczba kanałów w matrycy
Arijit
3
^ Jaka jest zatem różnica między C5 a C (5)?
Mateen Ulhaq
1
Nie ma różnicy.
Kevin Johnsrude
1
Dzięki. To powinna być najlepsza odpowiedź
regomodo
32

W nagłówku OpenCV " types_c.h " znajduje się zestaw definicji, które je generują, na przykład format to CV_bits{U|S|F}C<number_of_channels>
SoCV_8UC3 8-bitowe znaki bez znaku, 3 kanały kolorów - każda z tych nazw jest mapowana na dowolną liczbę całkowitą z makrami w tym pliku.

Edycja: zobacz „ types_c.h ” na przykład:

#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

Tak CV_8UC3 = 16 , ale nie mają korzystać z tego numeru, wystarczy sprawdzić type() == CV_8UC3, jeśli chcesz wiedzieć, jaki rodzaj wewnętrznej tablicy OpenCV jest.
Pamiętaj, że OpenCV przekonwertuje jpeg na BGR (lub skalę szarości, jeśli przekażesz '0' imread) - więc nie mówi ci nic o oryginalnym pliku.

Martin Beckett
źródło
Warto wiedzieć, że types_c.hznajduje się on w module podstawowym, np. Jeśli masz OpenCV zainstalowany bezpośrednio na dysku C w folderze opencv_2.4.11, plik nagłówkowy będzie w C: \ opencv_2.4.11 \ build \ include \ opencv2 \ core \ types_c .h
user3731622,
Ponadto, jeśli korzystasz ze środowiska IDE, które zawiera funkcję „przejdź do definicji”, na przykład Visual Studio, możesz wpisać cv::CV_8Uprawym przyciskiem myszy i wybrać, Go to Definitionaby otworzyć plik, w którym cv::CV_8Uzdefiniowano types_c.h.
user3731622
12

Zawsze używam tego linku, aby zobaczyć, jakiego typu jest numer, który otrzymuję type():
LISTA TYPÓW MAT W OPENCV
Mam nadzieję, że to ci pomoże.

Angie Quijano
źródło
8

Dodałem trochę użyteczności do funkcji z odpowiedzi @Octopus, do celów debugowania.

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
źródło
6

Odpowiedziało na to kilka innych osób, ale znalazłem rozwiązanie, które działało naprawdę dobrze.

System.out.println(CvType.typeToString(yourMat));
ProgrammingCuber
źródło