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 |
'Studynote > Computer Science 12' 카테고리의 다른 글
Chapter_03_간단한 그래픽 및 마우스 이벤트 (0) | 2018.11.03 |
---|---|
Chapter_02_3_IplImage 영상 자료구조 (0) | 2018.11.03 |
Chapter_02_1_CvPoint_CvScalar_CvSize_CvRect (0) | 2018.11.03 |
Chapter_01_OpenCV_개요 (0) | 2018.11.03 |
Skill Tree (0) | 2017.12.26 |
댓글