Як дізнатися, який тип об'єкта Mat є Mat: type () у OpenCV


118

Я на зразок плутанини з type()методом Matоб'єкта в OpenCV.
Якщо у мене є такі рядки:

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

і type = 16. Як дізнатись, що таке матриця матів ?.
Я намагався знайти відповідь у її посібнику чи в декількох книгах даремно.


6
Для людської інтерпретації віддайте перевагу використанню depth()та channels()замість того, щоб використовувати, type()яка повертає складну суміш між типом даних та кількістю каналів.
BConic

@Aldur, повернене значення глибини () все ще не читабельно для людини. ви повинні порівняти його з визначеннями: CV_8U, CV_8S тощо ...
Восьминіг,

1
@octopus впевнений, але, трохи практикуючи, ви можете дізнатися загальні depth()коди, що набагато складніше type().
BConic

Зверніть увагу, що deep () повертає значення CV для цього типу (трохи вводячи в оману для початківців). Якщо вам потрібен розмір одного числа, що зберігається в Маті в байтах, використовуйте Mat.elemSize1 (). Якщо вам потрібен тип під час виконання, наприклад, у межах функції, де в нього передаються різні типи, ви можете знайти тип шаблону TypeDepth <> (можливо, ми повинні перейменувати його, оскільки він не має глибини CV) тут: stackoverflow.com/questions/ 15245262 /…
Карстен

Відповіді:


196

Ось зручна функція, за допомогою якої можна визначити матриці opencv під час виконання. Я вважаю це корисним для налагодження, принаймні.

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

Якщо Mце тип типу, Matви можете назвати його так:

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

Виведе такі дані, як:

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

Варто зазначити, що існують також методи Matrix Mat::depth()і Mat::channels(). Ця функція є просто зручним способом отримання зрозумілої для людини інтерпретації з поєднання тих двох значень, біти яких зберігаються в одному значенні.


7
Спасибі за цю функцію, ви значно полегшили моє життя! Розчаровуючи, що така функція вже не інтегрована у opencv thow.
Міланія

1
Я створив Gist методом з відповіді в Objective-C. Насолоджуйтесь!
Tomasz Bąk

1
Для огляду типів також дивіться цю відповідь (5 = 32F, 6 = 64F): stackoverflow.com/questions/12335663/…
Ленар Хойт

Чи може хтось насправді перетворити це на зручну функцію для openCV?
Sharan Duggirala

1
Щоб отримати depthі chansви могли використовувати макроси CV_MAT_DEPTH(type)і CV_MAT_CN(type), відповідно. Їх також повинен бути тип int, що дозволить вам використовувати to_string(chans)замість chans+'0'.
Іван,

151

Для налагодження на випадок, якщо ви хочете шукати необроблений Mat :::

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

Так, наприклад, якщо type = 30, то тип даних OpenCV - CV_64FC4. Якщо тип = 50, то типом даних OpenCV є CV_16UC (7).


6
Що означає C (X)?
alanwsx

5
^ Кількість каналів у матриці
Arijit

3
^ Яка різниця між C5 і C (5)?
Mateen Ulhaq

1
Різниці немає.
Кевін Джонсруде

1
Дякую. Це має бути головна відповідь
regomodo

32

У заголовку OpenCV " types_c.h " є набір визначень, які генерують їх, формат. CV_bits{U|S|F}C<number_of_channels>
Так, наприклад, CV_8UC3означає 8 бітові неподписані символи, 3 кольорові канали - кожен з цих імен відображається на довільне ціле число з макросами цього файлу.

Редагувати: див. " Тип_c.h ", наприклад:

#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

Отже, CV_8UC3 = 16 але ви не повинні використовувати це число, просто перевірте, type() == CV_8UC3чи потрібно знати, що таке внутрішній масив OpenCV.
Пам'ятайте, що OpenCV перетворить jpeg в BGR (або сіру шкалу, якщо ви перейдете "0" до imread), тому він нічого не розповість про вихідний файл.


Корисно знати, що types_c.hвін знаходиться в основному модулі, наприклад, якщо у вас встановлений OpenCV безпосередньо на диску C в папці opencv_2.4.11, файл заголовка знаходитиметься в C: \ opencv_2.4.11 \ build \ include \ opencv2 \ core \ types_c .h
користувач3731622

Крім того, якщо ви використовуєте IDE, який включає функцію "go do definition" (наприклад, Visual Studio), ви можете набрати cv::CV_8Uправою кнопкою миші та вибрати, Go to Definitionщоб відкрити файл там, де cv::CV_8Uвизначено, що є types_c.h.
користувач3731622


8

Я додав деяку зручність функції до відповіді від @Octopus для налагодження.

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

На це відповіли декілька інших, але я знайшов рішення, яке дуже добре працювало для мене.

System.out.println(CvType.typeToString(yourMat));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.