Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++와 OpenCV로 단일 채널 이미지의 픽셀 값 읽는 방법

디지털 이미지는 수많은 픽셀(pixel)로 구성되어 있습니다. OpenCV를 사용하면 이미지의 픽셀 값을 손쉽게 읽을 수 있지만, 픽셀 값을 제대로 얻기 위해서는 단일 채널(single channel) 형태로 변환한 후 각각 따로 처리해야 합니다.

이 글에서는 컬러 이미지를 그레이스케일(단일 채널) 이미지로 변환한 뒤, 각 픽셀의 밝기 값을 콘솔 창에 출력하는 방법을 알아봅니다.

핵심 개념 정리

먼저 예제 코드에서 사용되는 주요 요소들을 살펴보겠습니다.

1. Mat 클래스

OpenCV에서 이미지는 Mat(매트릭스) 객체로 저장됩니다. 예제에서는 원본 컬러 이미지를 담을 cimage와, 변환된 결과를 저장할 img, 두 개의 Mat 객체를 사용합니다.

2. cvtColor 함수

cvtColor(cimage, img, COLOR_BGR2GRAY)는 BGR 3채널 컬러 이미지를 1채널 그레이스케일 이미지로 변환합니다. 그레이스케일 이미지의 각 픽셀은 0(검정)부터 255(흰색) 사이의 하나의 명도 값만 가집니다.

3. at<uchar> 메서드

img.at<uchar>(i, j)를 사용하면 (i, j) 좌표에 해당하는 픽셀 값에 접근할 수 있습니다. uchar(unsigned char) 타입은 0~255 범위의 값을 저장하며, 이를 (int)로 형변환해야 숫자로 출력할 수 있습니다.

전체 예제 코드

다음 프로그램은 이미지를 로드한 후 그레이스케일로 변환하고, 모든 픽셀의 값을 콘솔 창에 출력합니다.

#include<iostream>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main() {
    int x;//픽셀 값을 저장할 정수 변수 선언//
    Mat cimage = imread("colors.jpg");//이미지 로드//
    Mat img;//변환된 이미지를 저장할 빈 행렬 선언//
    cvtColor(cimage, img, COLOR_BGR2GRAY);//로드한 이미지를 그레이스케일로 변환//
    for (int i = 0; i < img.rows; i++)//행(row) 반복 루프// {
        for (int j = 0; j < img.cols; j++)//열(column) 반복 루프// {
            x = (int)img.at<uchar>(i, j);//(i, j) 위치의 픽셀 값을 변수에 저장//
            cout << "Value of pixel" << "(" << i << "," << j << ")" << "=" << x << endl;//콘솔 창에 값 출력//
        }
    }
    imshow("Show", img);//이미지 화면에 표시//
    waitKey();//키보드 입력 대기//
    return 0;
}

코드 동작 흐름

  1. 이미지 로드imread() 함수가 "colors.jpg" 파일을 읽어 cimage 행렬에 저장합니다.
  2. 채널 변환cvtColor()가 컬러 이미지를 그레이스케일로 변환하여 img에 저장합니다. 이 시점부터 이미지는 단일 채널입니다.
  3. 픽셀 순회 — 이중 for문으로 모든 행과 열을 순회하며 at<uchar>로 각 픽셀의 값을 읽어옵니다.
  4. 결과 출력 — 픽셀 좌표와 함께 해당 값을 콘솔에 출력하고, 최종적으로 imshow()로 변환된 이미지를 화면에 보여줍니다.

실행 결과

프로그램을 실행하면 다음과 같이 각 픽셀의 좌표와 밝기 값이 콘솔 창에 순차적으로 출력됩니다.

C++와 OpenCV로 단일 채널 이미지의 픽셀 값 읽는 방법

참고 사항

  • 컬러(BGR 3채널) 이미지의 픽셀 값을 읽으려면 at<Vec3b>를 사용하고, [0], [1], [2] 인덱스로 각각 파랑, 초록, 빨강 채널에 접근해야 합니다.
  • 이미지 크기가 클 경우 콘솔 출력량이 매우 많아질 수 있으므로, 실습 시에는 작은 크기의 이미지를 사용하는 것이 좋습니다.
  • imread() 호출 직후 이미지가 정상적으로 로드되었는지 cimage.empty()로 확인하는 습관을 들이면 오류를 예방할 수 있습니다.