개강한 공대생 2024. 9. 6. 00:23

Pixel Access는 이미지에서 특정 위치의 픽셀 값을 가져오는 방법이다.

다음 코드를 살펴보자

그레이스케일 이미지와 컬러 이미지에서 특정 좌표의 픽셀 값을 어떻게 가져오는지를 보여주는 코드다.

 

image = imread("lena.png");

image_gray = imread("lena.png", 0);

이미지를 다음과 같이 선언했다고 해보자.

 

 

value = image_gray.at<uchar>(50, 100);

이 코드에서는 그레이스케일 이미지의 (50, 100) 좌표에 있는 픽셀 값을 가져오고 있다.

여기서 이 좌표값은 (세로, 가로)이다.

이 값은 uchar 타입으로, 픽셀의 밝기 값(0-255)을 나타낸다.

 

value_B = image.at<Vec3b>(50, 100)[0];

value_G = image.at<Vec3b>(50, 100)[1];

value_R = image.at<Vec3b>(50, 100)[2];

여기서는 컬러 이미지에서 (50, 100) 좌표의 픽셀 값을 Vec3b 타입으로 가져온다.

Vec3b는 BGR (Blue, Green, Red) 순서로 세 가지 값을 가지고 있다.

 

 

그럼 이번에는 데이터 멤버 접근 방식을 사용해 픽셀에 접근하는 방법에 대해서 알아보자

이 방법은 at 연산자를 사용하는 것보다 빠르지만, 그만큼 직접 메모리 주소를 다뤄야 하기 때문에 조금 더 복잡하다.

 

DATA_TYPE* data = (DATA_TYPE*)image.data;

이 부분에서는 image.data를 사용해 이미지의 데이터 버퍼에 직접 접근하고 있다.

image.data는 이미지의 첫 번째 픽셀을 가리키는 포인터다.

이 포인터를 DATA_TYPE*로 캐스팅해서 data 포인터로 사용하고 있다.

여기서 DATA_TYPE은 픽셀 데이터의 타입이다.

예를 들어 unsigned char 또는 Vec3b 같은 걸 쓸 수 있다.

 

data[WANT_ROW * image.cols + WANT_COL]

이 표현식은 이미지의 특정 좌표에 있는 픽셀 값에 접근하는 방법이다.

WANT_ROW * image.cols는 원하는 행에 있는 첫 번째 열의 픽셀로 이동하는 데 필요한 오프셋을 계산하고

그 후에 WANT_COL을 더해서 특정 열의 픽셀에 접근하게 되는 거다.

 

다음은 데이터 멤버 함수를 이용해서 이미지에서 픽셀 값을 직접 접근하는 예제 코드이다.

이미지를 다음과 같이 불러온다고 치자

 

image = imread("lena.png");
channels = image.channels();

 

image.channels()이라는 함수는 이미지의 채널 수를 반환한다.

컬러 이미지니까 channels는 3이 될 거다.

 

uchar* data = (uchar*)image.data;

 

image.data는 아까 말했던 이미지의 첫 번째 픽셀을 가리키는 포인터를 반환한다.

uchar* data = (uchar*)image.data는 이 포인터를 uchar*로 캐스팅해서 data라는 포인터에 저장한다.

여기서 uchar는 부호 없는 8비트 정수(unsigned char)를 의미한다. 

즉 픽셀 하나의 채널 값을 저장할 수 있는 타입이다.

 

value_B = data[(50 * image.cols + 100) * channels + 0];
value_G = data[(50 * image.cols + 100) * channels + 1];
value_R = data[(50 * image.cols + 100) * channels + 2];

 

이 부분이 제일 중요하다.

여기서 (50 * image.cols + 100)는 (50, 100) 위치의 픽셀을 가리키는 오프셋을 계산하는 거다.

image.cols는 이미지의 가로 픽셀 수를 나타낸다.

* channels를 해주는 이유는 각 픽셀이 B, G, R 세 개의 값을 가지고 있기 때문이다.

그래서 (50 * image.cols + 100) 위치의 픽셀은 3개의 연속된 값(blue, green, red)으로 저장돼있다.

+0은 Blue 채널, +1은 Green 채널, +2는 Red 채널 값을 가져오는거다.