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

C++와 OpenCV로 다중 채널 이미지의 픽셀 값 읽는 방법 — at 완벽 가이드

개요

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)만 처리하면 연산량을 크게 줄일 수 있습니다.