2013-03-06 16 views
31

Sono confuso dai tipi di elemento OpenCV Mat. Questo è dalla documentazione:Tipi di elemento OpenCV Mat e loro dimensioni

There is a limited fixed set of primitive data types the library can operate on. 
That is, array elements should have one of the following types: 

8-bit unsigned integer (uchar) 
8-bit signed integer (schar) 
16-bit unsigned integer (ushort) 
16-bit signed integer (short) 
32-bit signed integer (int) 
32-bit floating-point number (float) 
64-bit floating-point number (double) 
... 

For these basic types, the following enumeration is applied: 
enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 }; 

E 'noto che di serie C++ non definisce la dimensione dei tipi di base in byte, così come si fa usano tali presupposti? E che tipo dovrei aspettarmi, diciamo, CV_32S, è int32_t o int?

+2

tipi in OpenCV sono abbastanza facili da capire. CV_numbitsType. Quindi CV_16S è un intero con segno di 16 bit. –

+0

Allora perché stanno usando tali nomi per loro nei documenti (int, float, ecc.) Mentre int (ad esempio) può essere 64 bit anziché 32? – lizarisk

+2

Non conosco la struttura sottostante ma quando hai un tappetino creato con tipo CV_32S: 'Mat myMat (10,10, CV_32S);' ti accedi con 'myMat.at (1,1) = 1; ' – sfotiadis

risposta

-3

In breve, la tabella fornita è corretta. Se si desidera accedere direttamente a un pixel, lo si è stampato sull'indicatore a destra, ad esempio CV_32S è un 32 bit firmato. Il S indica sempre un numero integrale firmato (firmato, firmato breve, firmato int) Il F indica sempre un numero in virgola mobile (float, doppio) U indica sempre un numero intero senza segno.

L'enumerazione viene utilizzata solo durante la creazione o la conversione di un supporto. È un modo per dire al tappeto che è il tipo desiderato, poiché capisco che è il predecessore di C quando i modelli non sono stati usati.

a utilizzare la funzione C esclusivamente, e al fine di creare un'immagine, sarebbe un errore per passare la seguente:

cvCreateImage(mySize,char, nChannels); 

Invece, passo il seguente:

cvCreateImage(mySize, IPL_DEPTH_8U, nChannels); 

Qui, l'IPL_DEPTH_8U è un flag utilizzato dalla funzione. La funzione stessa ha un'istruzione switch-type che controlla il flag. Il valore effettivo della bandiera è spesso privo di significato in quanto è spesso controllato da dichiarazioni condizionali, non algebriche.

+0

Questo è irrilevante. La domanda è su opencv2 e la risposta si riferisce a opencv1 – mkuse

2

In core.hpp è possibile trovare il seguente:

/*! 
    A helper class for cv::DataType 

    The class is specialized for each fundamental numerical data type supported by OpenCV. 
    It provides DataDepth<T>::value constant. 
*/ 
template<typename _Tp> class DataDepth {}; 

template<> class DataDepth<bool> { public: enum { value = CV_8U, fmt=(int)'u' }; }; 
template<> class DataDepth<uchar> { public: enum { value = CV_8U, fmt=(int)'u' }; }; 
template<> class DataDepth<schar> { public: enum { value = CV_8S, fmt=(int)'c' }; }; 
template<> class DataDepth<char> { public: enum { value = CV_8S, fmt=(int)'c' }; }; 
template<> class DataDepth<ushort> { public: enum { value = CV_16U, fmt=(int)'w' }; }; 
template<> class DataDepth<short> { public: enum { value = CV_16S, fmt=(int)'s' }; }; 
template<> class DataDepth<int> { public: enum { value = CV_32S, fmt=(int)'i' }; }; 
// this is temporary solution to support 32-bit unsigned integers 
template<> class DataDepth<unsigned> { public: enum { value = CV_32S, fmt=(int)'i' }; }; 
template<> class DataDepth<float> { public: enum { value = CV_32F, fmt=(int)'f' }; }; 
template<> class DataDepth<double> { public: enum { value = CV_64F, fmt=(int)'d' }; }; 
template<typename _Tp> class DataDepth<_Tp*> { public: enum { value = CV_USRTYPE1, fmt=(int)'r' }; }; 

Si può vedere che CV_32S è il valore per il tipo di int, non int32_t.

0

Ho trovato diversi #define nel codice di OpenCV relativo a CV_8UC1, CV_32SC1, ecc. Per rendere operative le enumerazioni, OpenCV inserisce codici aggiuntivi per convertire i numeri semplici insieme come parametro (ad esempio, CV_8UC1, CV_16UC2 ... sono tutti rappresentati dai rispettivi numeri) e suddividono la profondità e i canali nella definizione di CvMat (immagino che Mat possa avere codici simili nella sua definizione). Quindi, utilizza create() per allocare spazi per la matrice. Poiché create() è in linea, posso solo supporre che sia simile a malloc() o qualcosa del genere.
Siccome i codici sorgente cambiano molto da 2.4.9 a 3.0.0, ho bisogno di postare più prove in seguito. Per favore concedimi un po 'di tempo per saperne di più e modifica la mia risposta.

1

Mentre C++ non definisce la dimensione di un elemento, la domanda è ipotetica: per i sistemi su cui OpenCV viene eseguito, le dimensioni sono note. Dato

cv::Mat m(32,32,CV_32SC1, cv:Scalar(0)); 
std::cout << "size of the element in bytes: " << m.depth() << std::endl; 
std::cout << "or " << m.step.p[ m.dims-1 ]/m.channels() << std::endl; 

Così come si può essere sicuri che sia int?

Un tentativo di chiamare

int pxVal = m.at<int>(0,0); 

volontà

CV_DbgAssert(elemSize()==sizeof(int)); 

Quando la mano sinistra è definito tramite l'cv::Mat::flags - in questo esempio come la profondità predefinita del CV_32SC1 pari a

CV_DbgAssert(m.depth() == sizeof(int)) 

o

CV_DbgAssert(4 == sizeof(int)) 

Quindi, se ci sei riuscito, sei rimasto solo l'endianità. E ciò è stato verificato quando è stato generato cvconfig.h (da CMake).

TL; DR, si aspettano i tipi indicati nell'intestazione e starai bene.

+0

m.depth() non è in byte, ma fornisce valore enum EV per il tipo, ad es. CV_8U. – karsten

+0

usa invece elemSize1(). Si noti che elemSize() == elemSize1() * channels() – karsten

4

in via di sviluppo da Miki's answer,
In OpenCV 3 definizione si è spostato ai moduli/core/include/opencv2/core/traits.hpp, dove si possono trovare:

/** @brief A helper class for cv::DataType 

The class is specialized for each fundamental numerical data type supported by OpenCV. It provides 
DataDepth<T>::value constant. 
*/ 
template<typename _Tp> class DataDepth 
{ 
public: 
    enum 
    { 
     value = DataType<_Tp>::depth, 
     fmt = DataType<_Tp>::fmt 
    }; 
}; 



template<int _depth> class TypeDepth 
{ 
    enum { depth = CV_USRTYPE1 }; 
    typedef void value_type; 
}; 

template<> class TypeDepth<CV_8U> 
{ 
    enum { depth = CV_8U }; 
    typedef uchar value_type; 
}; 

template<> class TypeDepth<CV_8S> 
{ 
    enum { depth = CV_8S }; 
    typedef schar value_type; 
}; 

template<> class TypeDepth<CV_16U> 
{ 
    enum { depth = CV_16U }; 
    typedef ushort value_type; 
}; 

template<> class TypeDepth<CV_16S> 
{ 
    enum { depth = CV_16S }; 
    typedef short value_type; 
}; 

template<> class TypeDepth<CV_32S> 
{ 
    enum { depth = CV_32S }; 
    typedef int value_type; 
}; 

template<> class TypeDepth<CV_32F> 
{ 
    enum { depth = CV_32F }; 
    typedef float value_type; 
}; 

template<> class TypeDepth<CV_64F> 
{ 
    enum { depth = CV_64F }; 
    typedef double value_type; 
}; 

In la maggior parte del casi/compilatori si dovrebbe andare bene con i tipi di dati esatti C++. Non si avranno problemi con i tipi di dati a byte singolo (CV_8U ->uint8_t e CV_8U ->int8_t) come unambiguously defined in C++. Lo stesso per float (32bit) and double (64bit). Tuttavia, è vero che per altri tipi di dati per essere completamente sicuri di utilizzare il tipo di dati corretto (ad esempio quando si utilizza il metodo at<>) si dovrebbe usare per esempio:

typedef TypeDepth<CV_WHATEVER_YOU_USED_TO_CREATE_YOUR_MAT>::value_type access_type; 
myMat.at<access_type>(y,x) = 0; 

Come nota a margine, sono sorpreso hanno deciso di adottare un approccio così ambiguo, invece di utilizzare semplicemente tipi di dati precisi.

Pertanto, per quanto riguarda la tua ultima domanda:

Che dovrei aspettare da, diciamo, CV_32S?

Credo che la risposta più precisa, in OpenCV 3, è:

TypeDepth<CV_32S>::value_type 
+0

Ottima risposta grazie .. OpenCV non segue la calunnia C++ nella maggior parte dei casi. Sebbene sia una fantastica libreria per la visione artificiale, odio occuparmene in C++. frena sempre il mio codice e mi fa scrivere dei codici che mi vergogno di loro. –

+0

Come si accede a value_type? Il tuo esempio non funziona per me in OpenCV 3.0, perché è un membro e non pubblico. – John

+0

@John: sì, basta sostituire "class" con "struct", quindi funziona. Con la mia versione OpenCV 2.4.5 non esiste alcun hader, ho dovuto aggiungere il codice manualmente alle mie fonti. Si prega di notare il metodo Mat :: elemSize1() che mostra anche le dimensioni in byte di un numero memorizzato in Mat. – karsten