2009-11-11 17 views
14

Wyobraźmy mam następujące:Jaka jest struktura pamięci cvMat OpenCV?

CvMat* mat = cvCreateMat(3,3,CV_16SC3) 

Jest to macierz 3x3 liczb całkowitych kanału 3.

Teraz, jeśli spojrzeć na dokumentacji OpenCV znajdziesz następujące jako zwalniania dla cvMat:

typedef struct CvMat { 

int type; 
int step; 

int* refcount; 

union 
{ 
    uchar* ptr; 
    short* s; 
    int* i; 
    float* fl; 
    double* db; 
} data; 

union 
{ 
    int rows; 
    int height; 
}; 

union 
{ 
    int cols; 
    int width; 
}; 
} CvMat; 

Teraz chcę się pobawić plikiem data.ptr, który jest wskaźnikiem do danych przechowywanych w cvMat. Jednak ciężko mi zrozumieć, w jaki sposób pamięć jest rozkładana. Jeśli mam matrycę 3-kanałową, jak to działa? Dla jednego kanału jest to proste, ponieważ jest to po prostu prosta macierz MxN, gdzie M jest rzędem, a N jest coliem. Jednak dla 3 kanałów, są tam 3 z tych macierzy MxN? Czy ktoś może mi pokazać, jak zająć się inicjalizacją macierzy 3-kanałowej za pośrednictwem narzędzia data.ptr i jak uzyskać dostęp do tych wartości? Dziękuję Ci.

+0

Zasadniczo to, do czego to pytanie sprowadza się, to w jaki sposób mam uzyskać dostęp, powiedzmy, kanał 2 z wiersza 2, kolumna 1? –

Odpowiedz

19

This webpage to doskonałe wprowadzenie do OpenCV 1.1. Polecam używać najnowszej wersji, Open CV 2.0, która ma ogólną klasę Mat, która obsługuje obrazy, matryce itp. W przeciwieństwie do OpenCV 1.1.

Powyższa strona zawiera szczegółowe następujące metody dostępu elementem w wielokanałowych obrazów:

dostępu pośredniego (ogólnie, ale nieefektywne, dostęp do każdego rodzaju obrazu)

Dla multi- pływak kanał (lub bajt) image:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); 
CvScalar s; 
s=cvGet2D(img,i,j); // get the (i,j) pixel value 
printf("B=%f, G=%f, R=%f\n",s.val[0],s.val[1],s.val[2]); 
s.val[0]=111; 
s.val[1]=111; 
s.val[2]=111; 
cvSet2D(img,i,j,s); // set the (i,j) pixel value 

Bezpośredni dostęp: (Efficient dostępu, ale podatne na błędy)

przypadku obrazu wielokanałowy float:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); 
((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B 
((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G 
((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R 

bezpośredni dostęp przez wskaźnik: (uproszczony i wydajny dostęp zgodnie z założeniami ograniczającymi)

dla obrazu wielokanałowy float (zakładając 4 -bajtowych wyrównanie):

IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); 
int height  = img->height; 
int width  = img->width; 
int step  = img->widthStep/sizeof(float); 
int channels = img->nChannels; 
float * data = (float *)img->imageData; 
data[i*step+j*channels+k] = 111; 

Bezpośredni dostęp za pomocą C++ wrapper: (Prosty i wydajny dostęp)

zdefiniować C++ opakowanie dla obrazów jednokanałowych bajtowych, wielokanałowy obrazów bajtów i wielokanałowych obrazów float:

template<class T> class Image 
    { 
    private: 
    IplImage* imgp; 
    public: 
    Image(IplImage* img=0) {imgp=img;} 
    ~Image(){imgp=0;} 
    void operator=(IplImage* img) {imgp=img;} 
    inline T* operator[](const int rowIndx) { 
     return ((T *)(imgp->imageData + rowIndx*imgp->widthStep));} 
    }; 

    typedef struct{ 
    unsigned char b,g,r; 
    } RgbPixel; 

    typedef struct{ 
    float b,g,r; 
    } RgbPixelFloat; 

    typedef Image<RgbPixel>  RgbImage; 
    typedef Image<RgbPixelFloat> RgbImageFloat; 
    typedef Image<unsigned char> BwImage; 
    typedef Image<float>   BwImageFloat; 

przypadku obrazu wielokanałowy float:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); 
RgbImageFloat imgA(img); 
imgA[i][j].b = 111; 
imgA[i][j].g = 111; 
imgA[i][j].r = 111; 
+1

dziękuję za tę pełną odpowiedź – user261002

+2

Ta odpowiedź powinna zawierać kilka szczegółów na temat cvMat. cvMat w ogóle się nie wspomina – vishal