OpenCV'de Mat :: type () ile bir Mat nesnesinin ne tür olduğunu bulma


118

OpenCV'deki nesne type()yöntemiyle biraz kafam karıştı Mat.
Aşağıdaki satırlarım varsa:

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

ve type = 16. Matrisin ne tür bir matris olduğunu nasıl öğrenebilirim?
Cevabı el kitabında ya da birkaç kitapta boşuna bulmaya çalıştım.


6
İnsan yorumu için, veri türü ve kanal sayısı arasında karmaşık bir karışım döndüren hangisinin kullanılması yerine depth()ve kullanımını tercih edin . channels()type()
BConic

@Aldur, derinliğin () dönüş değeri hala insan tarafından okunabilir değil. bunu şu tanımlarla karşılaştırmalısınız: CV_8U, CV_8S, vb ...
Octopus

1
@octopus elbette, ancak biraz pratikle ortak depth()kodları öğrenebilirsiniz , ki bu çok daha zordur type().
BConic

Lütfen, derinliğin () bu tür için CV enum değerini döndürdüğünü unutmayın (yeni başlayanlar için biraz yanıltıcıdır). Mat'ta bayt olarak saklanan bir sayının boyutuna ihtiyacınız varsa Mat.elemSize1 () kullanın. Türe çalışma zamanında ihtiyacınız varsa, örneğin farklı türlerin aktarıldığı bir işlev içinde, burada TypeDepth <> şablon türünü bulabilirsiniz (belki de CV derinliği olmadığı için yeniden adlandırmalıyız): stackoverflow.com/questions/ 15245262 / ...
Karsten

Yanıtlar:


196

Çalışma zamanında açıklık matrislerinizi tanımlamanıza yardımcı olması için kullanabileceğiniz kullanışlı bir işlev. En azından hata ayıklama için yararlı buluyorum.

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

Bir Mtür çeşitiyse, Matşöyle diyebilirsiniz:

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

Aşağıdaki gibi verileri çıkarır:

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

Matrix yöntemleri Mat::depth()ve Mat::channels(). Bu fonksiyon, bitleri aynı değerde depolanan bu iki değerin kombinasyonundan insanlar tarafından okunabilir bir yorum elde etmenin kullanışlı bir yoludur.


7
Bu işlev için teşekkürler, hayatımı çok kolaylaştırdın! Böyle bir işlevin zaten opencv thow'a entegre edilmemiş olması hayal kırıklığı yaratıyor.
Milania

1
Gist'i Objective-C'deki cevaptan yöntemle oluşturdum. Zevk almak!
Tomasz Bąk

1
Türlere genel bir bakış için şu yanıta da bakın (5 = 32F, 6 = 64F): stackoverflow.com/questions/12335663/…
Lenar Hoyt

Birisi bunu openCV için gerçekten kullanışlı bir işlev haline getirebilir mi?
Sharan Duggirala

1
Almak depthve sırasıyla chansmakroları CV_MAT_DEPTH(type)ve kullanabilirsiniz CV_MAT_CN(type). Türleri de int, bunun to_string(chans)yerine kullanmanıza izin verecek şekilde olmalıdır chans+'0'.
John

151

Bir hata ayıklayıcıda ham bir Mat :: type aramak istemeniz durumunda hata ayıklama amacıyla:

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

Örneğin, tür = 30 ise OpenCV veri türü CV_64FC4'tür. Tür = 50 ise OpenCV veri türü CV_16UC (7) olur.


6
C (X) ne anlama geliyor?
alanwsx

5

3
^ C5 ve C (5) arasındaki fark nedir peki?
Mateen Ulhaq

1
Fark yok.
Kevin Johnsrude

1
Teşekkürler. En iyi cevap bu olmalı
regomodo

32

OpenCV üstbilgisinde " types_c.h ", bunları oluşturan bir dizi tanım vardır, biçim şu şekildedir CV_bits{U|S|F}C<number_of_channels>
: Örneğin CV_8UC3, 8 bit işaretsiz karakter, 3 renk kanalı anlamına gelir - bu adların her biri, o dosyadaki makrolarla rastgele bir tamsayı ile eşleşir.

Düzenleme: Örneğin " types_c.h " ye bakın :

#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

Yani CV_8UC3 = 16 bu sayıyı kullanmanız gerekmiyor, sadece type() == CV_8UC3dahili bir OpenCV dizisinin ne tür olduğunu bilmeniz gerekip gerekmediğini kontrol edin .
OpenCV'nin jpeg'i BGR'ye (veya '0'ı geçerseniz gri ölçeğe) dönüştürebileceğini unutmayın imread- böylece size orijinal dosya hakkında hiçbir şey söylemez.


Bunun types_c.hçekirdek modülde bulunduğunu bilmek yararlıdır , örneğin, OpenCV doğrudan bir C sürücüsüne opencv_2.4.11 klasöründe kuruluysa, başlık dosyası C: \ opencv_2.4.11 \ build \ include \ opencv2 \ core \ types_c konumunda olacaktır. .h
user3731622

Ayrıca, Visual Studio gibi "git tanıma" işlevini içeren bir IDE kullanıyorsanız, cv::CV_8Usağ tıklama yazabilir ve tanımlanmış olan Go to Definitiondosyayı açmayı seçebilirsiniz . cv::CV_8Utypes_c.h
user3731622


8

Hata ayıklama amacıyla @Octopus yanıtından işleve biraz kullanılabilirlik ekledim.

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

Bu birkaç kişi tarafından yanıtlandı ama benim için gerçekten işe yarayan bir çözüm buldum.

System.out.println(CvType.typeToString(yourMat));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.