본문 바로가기
Studynote/Computer Science 12

Chapter_02_2_CvMat 행렬 자료구조

by e.sunie 2018. 11. 3.

Chapter 02. OpenCV C API 자료구조


2.CvMat 행렬 자료구조


OpenCv는 2차원 행렬을 위해 자료구조 CvMat와 다양한 함수 지원


(1) CvMat

 

  • 주요 맴버변수
    • type : 행렬에 저장되는 요소의 자료형 지정

 

맴버변수

상수

상 수 설 명






type

CV_8UC1

8비트 , unsigned, 1채널

CV_8UC3

8비트 , unsigned, 3채널

CV_32SC1

32비트 , signed, 1채널

CV_32SC3

32비트 , signed, 3채널

CV_32FC1

32비트 , float, 1채널

CV_32FC3

32비트 , float, 3채널

CV_64FC1

64비트 , double, 1채널

CV_64FC3

64비트 , double, 3채널

채널 : 행렬을 여러 개 포갠 것으로 최대 4개 (R,G,B,alpha)까지 가능하다


 

    • step : 한 행의 바이트 수
    • row&col : 행렬의 행 크기와 열 크기 저장 , 행우선 순위 저장 메모리 바이트 크기 (행 )은 4의 배수
    • 행렬 요소의 첫 메모리 번지는 각 자료형에 따라 union data의 포인터 맴버, uchar *ptr, short *s, int *fl, double *db에 저장

 


CvMat 자료구조

typedefstructCvMat

{

inttype;

intstep;

int* refcount;

union

{

uchar* ptr;

short* s;

int* i;

float* fl;

double* db;

}data;

#ifdef __cplusplus

union

{

introws;

intheight;

};

union

{

intcols;

intwidth;

};

#else

introws;

intcols;

#endif

}CvMat;


 

 

(2)CvMat 행렬 생성 및 파괴

  • CvMat* cvCreateMat(int rows, int cols, int type);

행과 열의 크기를 주고 , 행렬요소의 자료형을 인수로 준다 .

→ 행렬의 해더를 생성 & 행렬요소를 저장하기 위한 메모리를 할당 ~포인터 반환


  • void cvReleaseMat(CvMat** mat);

    행렬 생성 시 할당된 메모리 해제

     

  • void cvSetReal2D(CvArr* arr, int idx0, int idx1, double value);

2차원 행렬 (CvMat)/영상 (IplImage) 포인터인 arr의 idx0행 idx1열의 요소 값에 value의 값 저장


  • double cvGetReal2D(const CvArr* arr, int idx0, int idx1);

2차원 행렬 (CvMat)/영상 (IplImage) 포인터인 arr의 idx0행 idx1열의 요소 값을 double형으로 반환


  • CvArr 자료형 (typedef void CvArr;)

void로 typedef되어 있는 자료형

목적 : 서로 다른 자료형 사이에 형변환을 위해 사용


CvCreateMat, cvReleaseMat, cvSetReal2D, cvGetReal2D

#include<iostream>

#include<opencv2/opencv.hpp>


intmain()

{

CvMat* pMat =cvCreateMat(2,3,CV_8UC1);

intx, y, nValue;

cvSetReal2D(pMat,0,0,1);

cvSetReal2D(pMat,0,1,2);//pMat  할당된 행렬의 0  1 열의 값을 2  저장

cvSetReal2D(pMat,0,2,3);

cvSetReal2D(pMat,1,0,4);

cvSetReal2D(pMat,1,1,5);

cvSetReal2D(pMat,1,2,6);

for(y=0; y<pMat->rows; y++)

{

for(x=0; x<pMat->cols; x++)

{

nValue = (int)cvGetReal2D(pMat, y, x);

// pMat  할당된 행렬에서 y  , x 열의 값을 반환해서 정수형으로 형변환하여 nValue  저장

printf("%4d", nValue );

}

printf("\n");

}

/*

for(r=0; r<pMat->rows;r++)

{

for(c=0; c<pMat->cols;c++)

{

nValue = (int)cvGetReal2D(pMat,r,c);

printf("%4d",nValue);

}

printf("\n");

}

y,x 대신 r,c  사용가능

: 변수의 이름은 사용자의 선택사항이므로 일관되고 의미에 맞게 사용되면 된다 .

*/

cvReleaseMat(&pMat);

return0;

}

1 2 3

4 5 6

Program ended with exit code: 0


  • CvMat* cvCreateMatHeader(int rows, int cols, int type);

행렬의 헤더를 생성하여 포인터를 반환

행렬 요소를 저장하기 위한 메모리 할당하지 않음

해더만 구상할 때 사용


  • void cvCreateData(CvArr* arr);

행렬 (CvMat)/영상 (IplImage) 포인터인 arr의 헤더에 맞게 행렬 또는 영상을 위한 메모리 할당


  • void cvReleaseData(CvArr* arr);

행렬 (CvMat)/영상 (IplImage) 포인터인 arr에 할당된 메모리만을 해제


CvCreateMatHeader, cvCreateData, cvReleaseData

#include<iostream>

#include<opencv2/opencv.hpp>


intmain()

{

intx, y, nValue;

CvMat* pMat =cvCreateMatHeader(2,3,CV_8UC1);

cvCreateData( pMat );//  함수가 없으면 cvSetReal2D 함수 호출시 실행 오류

//   줄을 합친 함수 : cvCreateMat 함수

cvSetReal2D(pMat,0,0,1);

cvSetReal2D(pMat,0,1,2);

cvSetReal2D(pMat,0,2,3);

cvSetReal2D(pMat,1,0,4);

cvSetReal2D(pMat,1,1,5);

cvSetReal2D(pMat,1,2,6);

for(y=0; y<pMat->rows; y++)

{

for(x=0; x<pMat->cols; x++)

{

nValue = (int)cvGetReal2D(pMat, y, x);

printf("%4d", nValue );

}

printf("\n");

}

cvReleaseData(pMat);

//pMat  type  CV_8UC1 ~ 데이터를 위한 메모리는 CvMat  uchar* ptr 맴버에 할당

//cvReleaseData 함수로 ptr  할당된 메모리 해제

cvReleaseMat(&pMat);

// 이미 cvReleaseData  데이터에 할당된 메모리 해제 ~ 생성된 해더를 위한 메모리만 해제

return0;

}

1 2 3

4 5 6

Program ended with exit code: 0



  • CvMat* cvInitMatHeader(CvMat* mat, int rows, int cols, int type, void* data=NULL, int step=CV_AUTOSTEP);

인수 rows, cols, type, data, step을 이용하여 CvMat포인터 인수 (mat)를 초기화

배열을 이용한 행렬의 초기화에 주로 사용


cvInitMatHeader를 이용한 배열데이터를 행렬에 초기화 1

#include<iostream>

#include<opencv2/opencv.hpp>


intmain()

{

intx, y, nValue;

CvMat* pMat =cvCreateMatHeader(2,3,CV_8UC1);

uchardata[ ] = {1,2,3,4,5,6};/* uchar == unsigned char*/

//uchar  배열 data  선언 & 1-6 정수로 초기화

// cvInitMatHeader(pMat, 1, 6, CV_8UC1, data );

//cvInitMatHeader(pMat, 3, 2, CV_8UC1, data );

/*

cvCreateHeader 함수에 의해 생성된 행렬 크기가 변경되며

행렬 요소의 값이 배열 data  값으로 초기화 된다 .

출력 결과 : 1 2 3 4 5 6

*/

cvInitMatHeader(pMat,2,3,CV_8UC1, data );

/*

cvCreateMatHeader 함수에 생성된 행렬의 크기과 자료형은 변경하지 않고

행렬 요소의 값을 배열 data  값으로 초기화 된다 .

*/

for(y=0; y<pMat->rows; y++)

{

for(x=0; x<pMat->cols; x++)

{

nValue = (int)cvGetReal2D(pMat, y, x);

printf("%4d", nValue );

}

printf("\n");

}

cvReleaseMat(&pMat);

return0;

}

1 2 3

4 5 6

Program ended with exit code: 0



cvInitMatHeader를 이용한 배열데이터를 행렬에 초기화 2

#include<iostream>

#include<opencv2/opencv.hpp>


/*

포인터를 사용하지 않고 CvMat 자료형 변수를 선언하고

cvInitMatHeader 함수를 이용하여 배열에 저장된 값으로 행렬 요소를 초기화한다 .

*/


intmain()

{

intx, y, nValue;

uchardata[ ] = {1,2,3,4,5,6};/* uchar == unsigned char*/

CvMatmat;//CvMat 자료형 변수 mat 선언 ~ 구조체 CvMat  맴버값이 초기화 되지 않는다 .

cvInitMatHeader(&mat,2,3,CV_8UC1, data );

for(y=0; y<mat.rows; y++)

{

for(x=0; x<mat.cols; x++)

{

nValue = (int)cvGetReal2D(&mat, y, x);

printf("%4d", nValue );

}

printf("\n");

}

return0;

}


1 2 3

4 5 6

Program ended with exit code: 0


  • CvMat cvMat(int rows, int cols, int type, void* data=NULL);

인수를 사용하여 CvMat 자료형의 인스턴스를 생성하여 반환


_cvMat함수를 이용한 행렬 초기화

#include<iostream>

#include<opencv2/opencv.hpp>


intmain()

{

intx, y, nValue;

uchardata[ ] = {1,2,3,4,5,6};/* uchar == unsigned char*/

CvMatmat =cvMat(2,3,CV_8UC1, data );

/*

CvMat mat;

cvInitMatDeader(&mat, 2, 3, CV_8UC1, data);

 동일

*/

for(y=0; y<mat.rows; y++)

{

for(x=0; x<mat.cols; x++)

{

nValue = (int)cvGetReal2D(&mat, y, x);

printf("%4d", nValue );

}

printf("\n");

}

return0;

}

1 2 3

4 5 6

Program ended with exit code: 0


 

 

 

(3)행렬 (CvMat)/영상 (IplImage) 요소 접근 (Get/Set)


요소 값 변경 함수 : cvSetReal*D & cvSet*D

요소 값을 읽는 함수 : cvGetReal*D & cvGet*D


cvmSet과 cvmGet함수는 영상에서 사용 불가 , 오직 1채널인 실수형 행렬에서만 사용

Ptr*D함수 : 행렬 /영상의 지정된 요소의 포인터를 반환 & 포인터를 이용하여 행렬 또는 영상의 요소 접근 가능


  • cvSetReal*D : 1 채널에서만 사용 가능

1채널 행렬 또는 영상에서만 사용 가능

행렬 또는 영상의 포인터 인수 arr의 위치 idx0 등 에 의해 지정된 요소 값을 double형 인수인 value값으로 변경한다 .

void cvSetReal1D(CvArr* arr, int idx0, double value); //1차원에서 사용

void cvSetReal2D(CvArr* arr, int idx0, int idx1, double value); //2차원

void cvSetReal3D(CvArr* arr, int idx0, int idx1, int idx2, double value); //3차원

void cvSetRealND(CvArr* arr, const int* idx, double value); //N차원 , idx포인터에 첨자배열전달


  • cvSet*D : 1,2,3 채널에서 사용

1,2,3 채널의 행렬 또는 영상에서 모두 사용가능

행렬 또는 영상의 포인터 인수 arr에서 idx0 등에 의해 지정된 요소 값을 CvScalar형 인수 value값으로 변경한다 .

void cvSet1D(CvArr* arr, int idx0, CvScalar value);

void cvSet2D(CvArr* arr, int idx0, int idx1, CvScalar value);

void cvSet3D(CvArr* arr, int idx0, int idx1, int idx2, CvScalar value);

void cvSetND(CvArr* arr, const int* idx, CvScalar value);


  • cvGetReal*D : 1 채널에서만 사용

1채널 행렬 또는 영상에서만 사용 가능

행렬 또는 영상의 포인터 인수 arr에서 idx0 등에 의해 지정된 요소 값을 double형으로 반환

double cvGetReal1D(const CvArr* arr, int idx0,);

double cvGetReal2D(const CvArr* arr, int idx0, int idx1,);

double cvGetReal3D(const CvArr* arr, int idx0, int idx1, int idx2);

double cvGetRealND(const CvArr* arr, const int* idx);

  • cvGet*D : 1,2,3 채널에서 사용

1,2,3 채널의 행렬 또는 영상에서 모두 사용 가능

행렬 또는 영상의 포인터 인수 arr에서 idx0 등에 의해 지정된 요소 값을 CvScalar형으로 반환

CvScalar cvGet1D(const CvArr* arr, int idx0;

CvScalar cvGet2D(const CvArr* arr, int idx0, int idx1);

CvScalar cvGet3D(const CvArr* arr, int idx0, int idx1, int idx2);

CvScalar cvGetND(const CvArr* arr, const int* idx);



  • cvmGet, cvmSet : 1 채널 , 실수 행렬 (CV_32FC1, CV_64FC1) 에서만 사용

1채널인 실숭 행렬에서만 사용 가능

cvmGet함수 : row, col 위치의 요소 값을 double형으로 반환

cvmSet함수 : row, col 위치의 요소 값을 value로 반환

double cvmGet(const CvMat* mat, int row, int col);

void cvmSet(CvMat* mat, int row, int col, double value);


CvGetReal2D, cvGet2D, cvmGet(CV_32FC1:1 채널 , 32 비트 , float 행렬 )

#include<iostream>

#include<opencv2/opencv.hpp>


intmain()

{

CvScalarelem;

intx, y;

floatfValue;

floatdata[ ] = {1,2,3,4,5,6};

CvMatmat =cvMat(2,3,CV_32FC1, data );

for(y=0; y<mat.rows; y++)

{

for(x=0; x<mat.cols; x++)

{

/* fValue = (float)cvGetReal2D(&mat, y, x); */

// 행렬 mat  1 채널 ~ Real 사용가능 : double  반환 &float 으로 형변환후 저장

fValue = (float)cvmGet(&mat, y, x);

//cvbGet 함수로 y  , x 열의 요소 값을 반환하여 실수형 변수 fValue  저장

printf("%.1f ", fValue);

/* elem = cvGet2D(&mat, y, x); */

//cvGet2D 함수 : y  x  요소 값을 CvScalar 형으로 반환 & 변수 elem  저장

/* printf("%.1f ", elem.val[0] ); */

// 행렬 mat  1 채널 ~ elem.val[0]  저장된 요소  출력

}

printf("\n");

}

return0;

}

1.0 2.0 3.0

4.0 5.0 6.0

Program ended with exit code: 0



CvGet2D (CV_8UC3 : 3 채널 , unsigned ,8 비트 , 행렬 )

#include<iostream>

#include<opencv2/opencv.hpp>


intmain()

{

intx, y;

CvScalarelem;

chardata[ ] = {1,2,3,4,5,6,

7,8,9,10,11,12,

13,14,15,16,17,18};

CvMatmat =cvMat(2,3,CV_8UC3, data );

for(y=0; y<mat.rows; y++)

{

for(x=0; x<mat.cols; x++)

{

elem =cvGet2D(&mat, y, x);

printf("(%2d, %2d, %2d)",

(int)elem.val[0], (int)elem.val[1], (int)elem.val[2] );

}

printf("\n");

}

return0;

}



( 1, 2, 3)( 4, 5, 6)( 7, 8, 9)

(10, 11, 12)(13, 14, 15)(16, 17, 18)

Program ended with exit code: 0



  • cvPtr*D 함수 : 1,2,3 채널에서의 사용

주어진 행렬 또는 영상에서 첨자 (idx0,idx1,idx2)로 지정된 요소의 포인터를 반환

행렬 요소의 자료형에 맞게 형변환하여 사용

type 생략 가능 , 행렬 또는 영상의 요소의 자료형 반환

Uuchar* cvPtr1D(const CvArr* arr, int idx0, int* type=NULL);

uchar* cvPtr2D(const CvArr* arr, int idx0, int idx1, int* type=NULL);

uchar* cvPtr3D(const CvArr* arr, int idx0, int idx1, int idx2, int* type=NULL);

uchar* cvPtrND(const CvArr* arr, const int* idx, int* type=NULL,

int create_node=1,unsigned* precalc_hashval=NULL);


cvPtr2D (CV_8UC1 : 1 채널 unsigned 8 비트 행렬 )

#include<iostream>

#include<opencv2/opencv.hpp>


intmain()

{

intx, y;

uchardata[ ] = {1,2,3,4,5,6};/* uchar == unsigned char*/

uchar*ptr;

CvMatmat =cvMat(2,3,CV_8UC1, data );

for(y=0; y<mat.rows; y++)

{

for(x=0; x<mat.cols; x++)

{

ptr =cvPtr2D( &mat, y, x);// get

*ptr +=10;// set

printf("%4d ", *ptr);

}

printf("\n");

}

return0;

}

11 12 13

14 15 16

Program ended with exit code: 0



cvPtr2D (CV_32SC3 : 3 채널 signed int ,32 비트 , 행렬 )

#include<iostream>

#include<opencv2/opencv.hpp>


intmain()

{

intx, y;

intdata[ ] = {1,2,3,4,5,6,

7,8,9,10,11,12,

13,14,15,16,17,18};

int*ptr;

CvMatmat =cvMat(2,3,CV_32SC3, data );

for(y=0; y<mat.rows; y++)

{

for(x=0; x<mat.cols; x++)

{

ptr = (int*)cvPtr2D( &mat, y, x);

printf(" (%4d, %4d, %4d) ", *ptr, *(ptr+1), *(ptr+2) );

}

printf("\n");

}

return0;

}

( 1, 2, 3) ( 4, 5, 6) ( 7, 8, 9)

( 10, 11, 12) ( 13, 14, 15) ( 16, 17, 18)

Program ended with exit code: 0



CvGetRealND, cvGet2D, cvPtrND

#include<iostream>

#include<opencv2/opencv.hpp>


intmain()

{

intx, y;

uchardata[ ] = {1,2,3,4,5,6};/* uchar == unsigned char*/

uchar*ptr;

intnValue;

CvScalarelem;

intidx[2];/* 2¬˜ø¯ ≪‡∑ƒ √∑¿¿˙¿A¿ª ¿ß≪— πEø≠ */

CvMatmat =cvMat(2,3,CV_8UC1, data );

for(y=0; y<mat.rows; y++)

{

for(x=0; x<mat.cols; x++)

{

idx[0] = y;

idx[1] = x;

nValue =cvGetRealND( &mat, idx);

printf("%4d", nValue);

// elem = cvGet2D(&mat, y, x);

// printf("%4d ", (int)elem.val[0] );

// ptr = cvPtrND( &mat, idx);

// printf("%4d", *ptr);

}

printf("\n");

}

return0;

}

1 2 3

4 5 6

Program ended with exit code: 0



  • cvSet, cvSetZero 함수

cvSet함수 : 행렬 또는 영상인 arr의 모든 요소 또는 화소의 값을 value로 변경

cvSetZero함수 : 모든 요소 또는 화소의 값을 0으로 변경

mask 행렬 또는 영상을 사용 ~ mask값이 0이 아닌 위치에만 선택적으로 value로 변경 가능

void cvSet(CvArr* arr, CvScalar value, const CvArr* mask=NULL);

void cvSetZero(CvArr* arr);



  • CV_MAT_ELEM 매크로함수 에 의한 행렬 요소 접근

cxtypes.h에 정의된 CV_MAT_ELEM 매크로 함수를 사용해서 행렬 요소 접근 가능

이 매크로 함수는 CV_MAT_ELEM_PTR_FAST 매크로 함수에 의해 다시 정의된다 .

행렬 mat : 포인터가 아닌 값 사용

row, col : 행렬 요소의 위치

elemtype : 행렬의 자료형 사용


-매크로 함수 : 단순 치환에 사용되는 함수 (컴파일러 전 처리 )

#define 함수 Name( 인자 )


CV_MAT_ELEM 매크로함수 에 의한 행렬 요소 접근 (CV_8UC1)

#include<iostream>

#include<opencv2/opencv.hpp>


intmain()

{

intx, y;

ucharvalue;

CvMat*pMat =cvCreateMat(2,3,CV_8UC1);

for(y=0; y<pMat->rows; y++)

for(x=0; x<pMat->cols; x++)

{

// CV_MAT_ELEM(*pMat, unsigned char, y, x) = (uchar)(x + y);

CV_MAT_ELEM(*pMat,uchar, y, x) = (uchar)(x + y);

}

for(y=0; y<pMat->rows; y++)

{

for(x=0; x<pMat->cols; x++)

{

value = (uchar)CV_MAT_ELEM(*pMat,uchar, y, x);

printf("%4d", value);

}

printf("\n");

}

return0;

}

0 1 2

1 2 3

Program ended with exit code: 0



CV_MAT_ELEM 매크로함수 에 의한 행렬 요소 접근 (CV_32SC2)

#include<iostream>

#include<opencv2/opencv.hpp>


intmain()

{

intx, y;

CvPointpt;

CvMat*pMat =cvCreateMat(2,3,CV_32SC2);

for(y=0; y<pMat->rows; y++)

for(x=0; x<pMat->cols; x++)

{

pt.x= x;

pt.y= y;

CV_MAT_ELEM(*pMat,CvPoint, y, x) = pt;

}

for(y=0; y<pMat->rows; y++)

{

for(x=0; x<pMat->cols; x++)

{

pt = (CvPoint)CV_MAT_ELEM(*pMat,CvPoint, y, x);

printf("(%2d, %2d)", pt.x, pt.y);

}

printf("\n");

}

return0;

}

( 0, 0)( 1, 0)( 2, 0)

( 0, 1)( 1, 1)( 2, 1)

Program ended with exit code: 0

매크로 함수 CV_MAT_ELEM에서 행렬의 자료형이 2채널 이상인 경우

행렬요소의 자료형인 elemtype 사용 가능

IF 해당 자료형이 없다면 구조체와 typedef문으로 정의하여 사용

mat의 자료형

elemtype

CV_32SC2

CvPoint

CV_32FC2

CvPoint2D32f

CV_32FC3

CvPoint3D32f

CV_64FC2

CvScalar



행렬 요소 직접 접근 CV_32SC2)

#include<iostream>

#include<opencv2/opencv.hpp>


intmain()

{

intx, y, k;

CvPointpt;

CvPoint*ptr;

CvMat*pMat =cvCreateMat(2,3,CV_32SC2);

for(y=0; y<pMat->rows; y++)

for(x=0; x<pMat->cols; x++)

{

k = y*pMat->cols +x;

pMat->data.i[2*k ] = x;

pMat->data.i[2*k+1] = y;

/*

k = y*pMat->step + x*sizeof(CvPoint);

ptr = (CvPoint *)(pMat->data.ptr + k);

ptr->x = x;

ptr->y = y;

*/

}

for(y=0; y<pMat->rows; y++)

{

for(x=0; x<pMat->cols; x++)

{

k = y*pMat->cols +x;

pt.x= pMat->data.i[2*k ];

pt.y= pMat->data.i[2*k+1];

/*

k = y*pMat->step + x*sizeof(CvPoint);

pt = *(CvPoint *)(pMat->data.ptr + k);

*/

printf("(%2d, %2d)", pt.x, pt.y);

}

printf("\n");

}

return0;

}

( 0, 0)( 1, 0)( 2, 0)

( 0, 1)( 1, 1)( 2, 1)

Program ended with exit code: 0


댓글