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.


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.


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).


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.


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


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;

}

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));
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.