728x90
반응형



OpenCV의 영상 데이터 구조체인 IplImage는 imageData라는 배열에 영상의 픽셀 정보를 저장한다. IplImage로부터 픽셀 값을 읽어오는 방법은 두가지로 분류된다.


1. 직접 imageData라는 배열에 접근해서 가져오는 방법

2. cvGet* 함수를 이용하는 방법







1. 픽셀에 직접 접근하는 방법


픽셀에 직접 접근하는 경우는 imageData에서 픽셀의 인덱스를 계산하여 값을 얻어온다. 인덱스를 계산할 때는 보통 widthStep을 이용한다. 왜냐하면 IplImage에서 row하나가 저장되는 메모리의 폭을 나타내게된다. 그러나 영상의 폭이 홀수로 끝나는 경우는 영상의 한 row가 저장되는 메모리 폭이 width와 다를 수 있기 때문에 x 좌표가 하나씩 밀리는 현상이 나타날 수 있다. 그렇기 때문에 width 보다는 widthStep을 이용하는 것이 안전하다.





 

IplImage* img = cvLoadImage("lena.png", 1);

	IplImage *red = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);
	IplImage *green = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);
	IplImage *blue = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);
	int i, j, nIdx;
	for (i = 0; i < img->height; i++)
	{
		for (j = 0; j < img->width; j++)
		{
			nIdx = i*img->widthStep + j*img->nChannels;

			red->imageData[nIdx + 2] = img->imageData[nIdx + 2];
			green->imageData[nIdx + 1] = img->imageData[nIdx + 1];
			blue->imageData[nIdx + 0] = img->imageData[nIdx + 0];
		}
	}

이러한 예제코드에서 볼 수 있듯


channel RGB 영상의 경우


int index = 3*x + y*widthStep;

unsigned char B = image->imageData[index];

unsigned char G = image->imageData[index+1];

unsigned char R = image->imageData[index+2];


이러한 형식으로 픽셀에 직접 접근 할 수 있다.



channel gray 영상의 경우에는


int index = x + y *image->widthStep;

unsigned char value = image->imageData[index];


이러한 형식으로 픽셀에 직접 접근 할 수 있다.









2. cvGet* 함수를 이용하는 방법



이 방법은 OpenCV가 제공해주는 cvGet 함수를 이용하는 것이다. 1채널 Gray 영상에는 cvGetReal2D() 함수를 사용하고 double 값을 이용한다. 다채널 영상(ex 3채널..)에서는 cvGet2D() 함수를 사용하고, CvScalar 구조체를 사용하여 각 채널별로 값을 저장해서 리턴한다. 특히, 함수의 인자가 알던 순서와는 다르게 반대이기 때문에 x, y 순서에 주의해야한다.





channel RGB 영상의 경우


double value = cvGetReal2D(iamge, y, x);







channel gray 영상의 경우


CvScalar value = cvGet2D(iamge, y, x);

double B = value.val[0];

double G = value.val[1];

double R = value.val[2];





cvGet* 함수를 쓰는 것 보다 imageData에 직접 접근하는 방법이 성능이 빠르다고 한다. 하지만 인덱스 계산할 필요 없이 픽셀 좌표만으로 데이터를 가져오는데는 함수를 이용하는 것이 더 편리한 것은 자명한 사실이다.











728x90
반응형