개요
OpenCV에서 컬러 이미지를 다룰 때 가장 기본적인 작업 중 하나는 특정 픽셀의 채널 값을 읽어오는 것입니다. 이 글에서는 C++를 사용하여 BGR 3채널 이미지에서 파랑·초록·빨강 각 채널의 픽셀 값을 읽고 콘솔 창에 출력하는 방법을 단계별로 살펴봅니다.
핵심 문법: at<Vec3b>
먼저 픽셀 값을 저장할 세 개의 변수인 blue_Channel, green_Channel, red_Channel을 선언합니다. 이 변수들은 반복문(for loop) 안에서 각 채널의 픽셀 값을 담는 역할을 하며, 이미지를 불러올 행렬(matrix)로는 color_image_Matrix를 선언합니다.
픽셀 값을 읽는 핵심 문법은 다음과 같습니다.
blue_Channel = color_image_Matrix.at<Vec3b>(i, j)[0];
OpenCV는 기본적으로 BGR 순서로 색상 채널을 저장합니다. 즉, 인덱스 0은 파랑(B), 1은 초록(G), 2는 빨강(R)을 의미합니다. at<Vec3b>(i, j)는 (i행, j열) 위치의 픽셀을 가리키며, 뒤에 붙는 대괄호 인덱스가 그 픽셀의 어느 채널을 지정할지 결정합니다.
예를 들어 다음 코드는,
blue_Channel = color_image_Matrix.at<Vec3b>(30, 35)[0];
(30, 35) 좌표에 있는 픽셀의 첫 번째 채널(파란색) 값을 blue_Channel 변수에 저장하라는 의미입니다. 이처럼 대괄호 인덱스만 바꾸면 원하는 채널의 값에 자유롭게 접근할 수 있습니다.
전체 예제 코드
아래 프로그램은 BGR 이미지의 모든 픽셀 값을 읽어 채널별로 구분한 뒤, 각 값을 콘솔 창에 출력합니다.
#include<iostream>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main() {
int blue_Channel;
int green_Channel;
int red_Channel;
Mat color_image_Matrix; // 이미지를 불러올 행렬 선언//
color_image_Matrix = imread("colors.jpg"); // 행렬에 이미지 로드//
// 파란색 채널 픽셀 값 읽기 반복문 시작//
for (int i = 0; i < color_image_Matrix.rows; i++) { // 행(row) 반복//
for (int j = 0; j < color_image_Matrix.cols; j++) { // 열(column) 반복//
// 첫 번째 채널(파란색)의 값 읽기//
blue_Channel = color_image_Matrix.at<Vec3b>(i, j)[0];
cout << "Value of pixel of blue channel" << "(" << i << "," << j << ")" << "="
<< blue_Channel << endl; // 콘솔 창에 값 출력//
}
}
// 파란색 채널 픽셀 값 읽기 반복문 끝//
// 초록색 채널 픽셀 값 읽기 반복문 시작//
for (int i = 0; i < color_image_Matrix.rows; i++) {
for (int j = 0; j < color_image_Matrix.cols; j++) {
// 두 번째 채널(초록색)의 값 읽기//
green_Channel = color_image_Matrix.at<Vec3b>(i, j)[1];
cout << "Value of pixel of green channel" << "(" << i << ","
<< j << ")" << "=" << green_Channel << endl;
}
}
// 초록색 채널 픽셀 값 읽기 반복문 끝//
// 빨간색 채널 픽셀 값 읽기 반복문 시작//
for (int i = 0; i < color_image_Matrix.rows; i++) {
for (int j = 0; j < color_image_Matrix.cols; j++) {
// 세 번째 채널(빨간색)의 값 읽기//
red_Channel = color_image_Matrix.at<Vec3b>(i, j)[2];
cout << "Value of pixel of red channel" << "(" << i << ","
<< j << ")" << "=" << red_Channel << endl;
}
}
// 빨간색 채널 픽셀 값 읽기 반복문 끝//
if (waitKey(0) == 27);
cout << "Image read successfully…!";
return 0;
}실행 결과
Image read successfully...
성능 관련 참고 사항
이 프로그램은 실행하는 데 몇 분 정도 걸릴 수 있습니다. 이미지의 모든 픽셀을 채널별로 하나씩 읽어 출력하기 때문입니다. 실무에서 더 나은 성능이 필요하다면 다음 방법들을 고려해 보세요.
- ptr 포인터 활용:
mat.ptr<Vec3b>(i)로 행 단위로 접근하면at()호출보다 빠르게 처리할 수 있습니다. - 릴리스 모드 빌드: 디버그 빌드에서는 최적화가 꺼져 있어 속도가 크게 저하되므로, 릴리스 모드로 컴파일하는 것이 좋습니다.
- ROI 활용: 전체 이미지가 아닌 관심 영역(Region of Interest)만 처리하면 연산량을 크게 줄일 수 있습니다.