OpenCV 자료구조

꾸준희
|2015. 12. 29. 20:50
728x90
반응형

2.1 CvPoint, CvScalar, CvSize, CvRect


CvPoint

영상을 행렬형태의 2차원 화소들의 집합으로 생각할 수 있는데 OpenCV는 각 화소 또는 2차원 점의 좌표를 표현하기 위해 CvPoint, CvPoint2D32f, CvPoint2D64f 등의 구조체를 사용한다. (각 int형 2D 화소 위치, float형 2D 화소 위치, double형 2D 화소 위치를 뜻함)


CvScalar

화소의 밝기 값 또는 컬러 값 표현을 위해 존재하는 함수이다. 이 함수는 4개의 인수(val0, val1, val2, val3)를 가지며, val0은 반드시 가져야하고, 나머지는 지정하지 않을 경우 0으로 간주된다.  ScalarAll 함수는 하나의 인수 val0123을 입력받아 배열 val에 동일한 값으로 초기화 하는 함수이다.

참고로 함수 이름에 Real이 들어간 함수는 채널이 1인 영상 또는 행렬에서 사용하는 함수이다.


그레이 스케일 영상일 경우 val[0]

컬러 영상일 경우

val[0] = B

val[1] = G

val[2] = R

val[3] = alpha


CvSize

영상 및 영역의 크기를 표현하기 위한 자료구조이며, 멤버로 width, height를 가지고 인스턴스 생성을 위한 인라인 함수는 cvSize 함수이다.


CvRect

사각형을 위한 자료구조이다. 왼쪽 상단 모서리 좌표(x,y)와 너비(width)와 높이(height)의 멤버를 갖는다. 인스턴스 생성을 위한 인라인 함수는 cvRect 함수이다.





2.2 CvMat 행렬 자료구조


(1) CvMat


이는 행렬 자료구조이고, 멤버변수로는 type, step, rows, cols를 가진다.


 멤버변수

 변수설명 

 상수 

 상수설명 

 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채널 

 step

 1행의 바이트 수

 rows

 행의 크기 

 cols

 열의 크기 



(2) CvMat 행렬 생성 및 파괴 


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

이 함수는 행과 열의 크기를 주고 CV_8UC1과 같은 행렬 요소의 자료형을 인수로 주면 행렬의 헤더를 생성하고 행렬 요소를 저장하기 위한 메모리를 할당하여 포인터를 반환한다. 여기서 행렬의 헤더를 생성한다는 의미는 CvMat 구조체의 멤버 변수를 초기화한다는 의미이다.



void cvReleaseMat(CvMat** mat);

이 함수는 행렬을 생성할 때 할당된 메모리를 헤제한다. 이중포인터인 것에 주의하라.


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

이 함수는 2차원 행렬 또는 영상 포인터인 arr의 idx0 행, idx1 열의 요소 값에 value의 값을 저장한다.

이와 같이 함수에 Real 문자가 포함된 경우는 1채널인 행렬 또는 영상에서만 사용 할 수 있다.


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

이 함수는 2차원 행렬 또는 영상 포인터인 arr의 idx0 행, idx1 열의 요소 값을 double 형으로 반환한다. 1채널인 행렬 또는 영상에서 사용 할 수 있다.


CvArr 자료형(typedef void CvArr);

이 자료형은 서로 다른 자료형 사이에 형 변환을 위해 사용되며, OpenCV 함수에서는 CvArr*의 형태로 주로 사용된다. cvSetReal2D와 cvGetReal2D 함수에서와 같이 CvMat* 또는 IplImage* 형태의 인수를 전달 받는데 사용한다. 각 요소 값을 변경하고, 읽어오는 함수로 사용된다.


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

이 함수는 행과 열의 크기를 주고 CV_8UC1 같은 행렬요소의 자료형을 인수로 주면, 행렬의 헤더를 생성하여 포인터를 반환한다. 이 때 행렬 요소를 저장하기 위한 메모리를 할당하지 않는 다는 것에 주의한다. 행렬의 헤더만을 생성하고, 자료를 위한 메모리는 나중에 생성하고자 할 때 사용한다.


void cvCreateData(CvArr* arr);

이 함수는 행렬 또는 영상 포인터인 arr에 헤더에 맞게 행렬 또는 영상을 위한 메모리를 할당한다.


void cvReleaseData(Cv Arr* arr)

이 함수는 행렬 또는 영상 포인터인 arr에 할당된 메모리만을 해제한다.


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

이 함수는 인수 rows, cols, type, step을 이용하여 CvMat 포인터 인수인 mat를 초기화한다. 이는 cvInitMatHeader 함수는 배열을 이용하여 행렬을 초기화 할 때 주로 사용한다.


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

이 함수는 인수 rows, cols, type, data를 사용하여 CvMat 자료형의 인스턴스를 생성하여 반환한다.





(3) 행렬(CvMat) 또는 영상(IpIImage)요소 접근(Get/Set)



cvSetReal*D 

1채널에서만 사용하며 행렬 또는 영상의 포인터 인수 arr의 위치 idx0, idx1, idx2 등에 의해 지정된 요소 값을 double형 인수인 value 값으로 변경한다.

cvSetRealND : N차원에서 사용


cvSet*D

1, 2, 3채널에서 사용한다. 이 함수는 행렬 또는 영상의 포인터 인수 arr에서 idx0, idx1, idx2 등에 의해 지정된 요소 값을 CvScalar형 인수인 value 값으로 변경한다.


cvGetReal*D

1채널에서만 사용하며 행렬 또는 영상의 포인터 인수 arr에서 idx0, idx1, idx2 등에 의해 지정된 요소 값을 double형으로 반환한다.

cvGetRealND : N차원


cvGet*D

1, 2, 3채널에서 사용하며 행렬 또는 영상의 포인터 인수 arr에서 idx0, idx1, idx2 등에 의해 지정된 요소 값을 CvScalar 형으로 반환한다.


cvmGet, cvmSet

1채널, 실수 행렬에서만 사용가능하다. cvmGet 함수는 row, col 위치의 요소 값을 double 형으로 반환하고, cvmSet 함수는 row, col 위치의 요소 값을 double 형 인수인 value로 변경한다.


cvPtr*D

이 함수는 주어진 행렬 또는 영상에서 첨자로 지정된 요소의 포인터를 반환한다. 행렬 요소의 자료형에 맞게 형 변환하여 사용한다. type은 생략 가능 하며 행렬 또는 영상의 요소의 자료형을 반환한다.


cvSet, cvSetZero

이 함수는 행렬 또는 영상인 arr의 모든 요소 또는 화소의 값을 value로 변경한다. cvSetZero 함수는 모든 요소 또는 화소의 값을 0으로 변경한다. mask 행렬 또는 영상을 사용하여 mask의 요소 값이 0이 아닌 위치에서만 선택적으로 value로 변경할 수 있다.




2.3 IplImage 영상 자료구조


(1) IplImage 자료형

이 구조체는 OpenCV에서 2차원 영상을 위한 자료구조이다.


(2) 파일에서 영상읽기 및 화면에 출력하기

IplImage* cvLoadImage(const char* filename, int iscolor=CV_LOAD_IMAGE_COLOR);

이 함수는 filename 파일에서 영상을 읽어오는 매우 중요한 함수이다. 인수 iscolor는 영상의 컬러를 지정하는 인수이다.

CV_LOAD_IMAGE_COLOR - 3채널 컬러 영상

CV_LOAD_IMAGE_GRAYSCALE - 1채널 그레이 스케일 영상

CV_LOAD_IMAGE_UNCHANGED - 원본영상


int cvSaveImage(const char* filename, const CvArr* image);

이 함수는 영상을 파일에 저장한다. 영상 포멧은 파일의 확장자에 의해 정해지며, 8비트 단일 채널과 3채널 컬러 영상으로 저장 할 수 있다.


int cvWaitKey(int delay = 0);

delay/1000초 만큼 지연대기한다. delay=0 이면 키를 누를 때 까지 무한히 대기한다.


int cvNamedWindow(const char* name, int flags);

name을 윈도우 캡션으로 사용하는 윈도우를 생성한다. name은 윈도를 식별하는 아이디로 사용하게된다. 윈도우의 크기를 영상의 크기에 맞게 자동 조절하는 flags = CV_WINDOW_AUTOSIZE 만을 지원한다.


void cvDestroyWindow(cnast char* name);

cvNamedWindow에 의해 생성된 윈도우를 파괴한다. 생성된 윈도우가 하나 이상 있 때 cvDestroyAllWindows(void) 함수에 의해 모든 윈도우를 한 번에 파괴할 수 도 있다.


void cvShowImage(const char* name, const CvArr* image);

name 이름을 갖는 윈도우에 영상 image를 보여준다. 영상의 크기에 맞게 윈도우의 크기가 스케일된다.





(3) IplImage 영상 생성 및 파괴



여기서는 영상을 생성하고 할당된 메모리를 제거하는 방법에 대해서 설명한다. 영상의 화소 값을 가져오고 변경하는 방법은 행렬에서 설명한 cvGetReal*D, cvGet*D, cvSetReal*D, cvSet*D 등의 함수를 사용한다.



IplImage* cvCreateImage(CvSize size, int depth, int channels);

이 함수는 size, width, height, depth, channels를 이용하여 영상의 IpiImage 헤더를 생성하고,

영상 데이터를 위한 메모리를 할당한다. 인터리브 채널 영상을 생성한다. 여기서 IplImage 헤더를 생성한다는 것은 구조체의 멤버변수를 초기화 한다는 의미다.


cvCreateImage 함수는 cvCreateImageHeader 함수를 호출하고, cvCreteData 함수를 호출 한 것과 같다.

cvCreateImage 함수는 입력영상에 대한 중간결과 또는 최종결과 영상을 위한 메모라 할당에 주로 사용한다.


IplImage* cvCreateImageHeader(CvSize size, int depth, int channels);

이 함수는 영상의 IplImage 헤더는 생성하지만, 영상 데이터를 위한 메모리는 할당하지 않는다.


void cvReleaseImage(IplImage** image);

이미지의 헤더와 영상을 위해 할당된 메모리를 해제한다. 인수 image가 이중 포인터임에 주의한다.


void cvReleaseImageHeader(IplImage** image);

이미지의 헤더를 위한 메모리만 해제한다. 인수 image가 이중 포인터임에 주의한다.


IplImage* cvInitImageHeader(IplImage* image, CvSize size, int depth, int channels, int origin=0, int align=4);

이 함수는 이미 생성된 영상 image의 헤더를 size, depth, channels, origin, align을 사용하여 초기화한 후에 포인터를 반환한다.


IpImage* cvCloneImage(const IplImage* image);

이 함수는 영상의 헤더, 데이터, ROI 모두를 복사한 다음 영상 포인터를 반환한다.


CV_IMAGE_ELEM 매크로 함수

이는 cxtypes.h에 정의된 CV_IMAGE_ELEM 매크로 함수를 사용하여 영상의 화소를 접근할 수 있다.

image에 영상 포인터, row, col에 영상의 화소 위치, elemtype은 영상의 자료형 및 채널 수에 맞는 char, uchar ... 등의 자료형을 사용한다.





실습 결과 화면 





실습 소스 코드


#include <opencv\cv.h>
#include <opencv\highgui.h>


int main()
{
	CvPoint pt0 = cvPoint(10, 20);
	CvPoint2D32f pt1 = cvPoint2D32f(30.0, 40.0);
	CvPoint2D64f pt2 = cvPoint2D64f(50.0, 60.0);

	CvScalar color1 = cvScalar(255, 255, 255);
	CvScalar color2 = cvScalar(255);
	CvScalar color3 = cvRealScalar(255);
	CvScalar color4 = cvScalarAll(255);

	CvSize size = cvSize(720, 480);
	CvRect rect = cvRect(100, 100, 400, 200);
	CvPoint pt11, pt22;

	// 행크기2, 열크기3인 8비트unsigned 1채널인 행렬을 생성하여 CvMat 구조체 포인터 변수 pMat에 저장
	// 행렬의 헤더를 생성(CvMat구조체의 멤버변수 초기화), 행렬 요소를 저장하기 위한 메모리를 할당하여 포인터를 반환
	CvMat* pMat = cvCreateMat(2, 3, CV_8UC1);
	int x, y, nValue;

	// cvCreateMat과는 다르게 행렬요소를 저장하기위한 메모리를 할당하지 않음
	// 자료를 위한 메모리는 나중에 할당하는 것이 특징, 오직 헤더만 생성함 
	int x1, y1, nValue1;
	CvMat* pMat1 = cvCreateMatHeader(2, 3, CV_8UC1);
	
	int x2, y2, nValue2;
	CvMat* pMat2 = cvCreateMatHeader(2, 3, CV_8UC1);
	uchar data[] = { 1, 2, 3, 4, 5, 6 };

	int x3, y3, nValue3;
	uchar data1[] = { 1, 2, 3, 4, 5, 6 };
	CvMat mat = cvMat(2, 3, CV_8UC1, data1);
/////////////////////2.3/////////////////////////
	IplImage *srcImage;
	int a, b;
	IplImage *srcImage1;


//////////////////////////////////////////////
	printf("<<< CvPoint, CvPoint2D32f, CvPoint2D64f >>>\n");
	printf("pt0 : %d, %d \n", pt0.x, pt0.y);
	printf("pt1 : %f, %f \n", pt1.x, pt1.y);
	printf("pt2 : %f, %f \n\n", pt2.x, pt2.y);
//////////////////////////////////////////////
	printf("<<< CvScalar >>>\n");
	printf("color1.val: %f, %f, %f, %f\n", color1.val[0], color1.val[1], color1.val[2], color1.val[3]);
	printf("color2.val: %f, %f, %f, %f\n", color2.val[0], color2.val[1], color2.val[2], color2.val[3]);
	printf("color3.val: %f, %f, %f, %f\n", color3.val[0], color3.val[1], color3.val[2], color3.val[3]);
	printf("color4.val: %f, %f, %f, %f\n\n", color4.val[0], color4.val[1], color4.val[2], color4.val[3]);
//////////////////////////////////////////////
	printf("<<< CvSize, CvRect, CvPoint >>>\n");
	printf("size : %d, %d \n", size.width, size.height);
	
	pt11.x = rect.x;
	pt11.y = rect.y;
	pt22.x = rect.x + rect.width;
	pt22.y = rect.y + rect.height;

	printf("Left Top Point(p1) : %d, %d\n", pt11.x, pt11.y);
	printf("Right Bottom Point(p2) : %d, %d\n\n", pt22.x, pt22.y);
//////////////////////////////////////////////
	printf("<<< CvCreateMat, cvReleaseMat, cvSetReal2D, cvGetReal2D >>>\n");
	// 함수에 Real문자가 포함된 경우는 1채널인 행렬 또는 영상에서만 사용 가능 
	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++){
			// 행렬 pMat에 할당된 행렬에서 y,x행 값을 반환한뒤, nValue에 저장 
			nValue = (int)cvGetReal2D(pMat, y, x);
			printf("%4d", nValue);
		}
		printf("\n");
	}
	cvReleaseMat(&pMat); // 행렬 pMat에 할당된 메모리 해제 
	printf("\n");


//////////////////////////////////////////////
	printf("<<< cvCreateMatHeader, cvCreateData, cvReleaseData >>>\n");
	
	cvCreateData(pMat1);
	cvSetReal2D(pMat1, 0, 0, 1);
	cvSetReal2D(pMat1, 0, 1, 2);
	cvSetReal2D(pMat1, 0, 2, 3);

	cvSetReal2D(pMat1, 1, 0, 4);
	cvSetReal2D(pMat1, 1, 1, 5);
	cvSetReal2D(pMat1, 1, 2, 6);

	for (y1 = 0; y1 < pMat1->rows; y1++){
		for (x1 = 0; x1 < pMat1->cols; x1++){
			nValue1 = (int)cvGetReal2D(pMat1, y1, x1);
			printf("%4d", nValue1);
		}
		printf("\n");
	}
	cvReleaseData(pMat1);
	cvReleaseMat(&pMat1);
	printf("\n");
//////////////////////////////////////////////
	printf("<<< cvInitMatHeader >>>\n");
	cvInitMatHeader(pMat2, 1, 6, CV_8UC1, data); 
	for (y2 = 0; y2 < pMat2->rows; y2++){
		for (x2 = 0; x2 < pMat2->cols; x2++){
			nValue2 = (int)cvGetReal2D(pMat2, y2, x2);
			printf("%4d", nValue2);
		}
		printf("\n");
	}
	cvReleaseMat(&pMat2);
	printf("\n");
//////////////////////////////////////////////
	printf("<<< cvMat >>>\n");
	for (y3 = 0; y < mat.rows; y++)
	{
		for (x3 = 0; x3 < mat.cols; x++)
		{
			nValue3 = (int)cvGetReal2D(&mat, y3, x3);
			printf("%4d", nValue3);
		}
		printf("\n");
	}

////////////////////2.3//////////////////////////

	printf("<<< 영상 불러오기 >>>\n");
	if ((srcImage = cvLoadImage("test.jpg")) == NULL)
		return -1;
	printf("colorModel			= %s \n",srcImage->colorModel);
	printf("channelSeq			= %s \n",srcImage->channelSeq);

	printf("image pixel size = %d x %d \n", srcImage->width, srcImage->height);
	printf("# of channel	= %d \n", srcImage->depth);

	cvNamedWindow("Seohee", CV_WINDOW_AUTOSIZE);
	cvShowImage("Seohee", srcImage);
	cvWaitKey(0);

	cvDestroyWindow("Seohee");
	cvReleaseImage(&srcImage);
//////////////////////////////////////////////
	srcImage1 = cvCreateImage(cvSize(512, 512), IPL_DEPTH_8U, 1);
	cvSet(srcImage1, cvScalar(255));

	for (b = 200; b < 200; b++)
		for (a = 200; a < 300; a++){
			cvSetReal2D(srcImage1, b, a, 0); // black
		}
	
	cvNamedWindow("srcImage1", CV_WINDOW_AUTOSIZE);
	cvShowImage("srcImage1", srcImage1);
	cvWaitKey(0);

	cvDestroyWindow("srcImage1");
	cvReleaseImage(&srcImage1);




	return 0;
}






728x90
반응형