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

OpenCV 직접 접근(Direct Access) 방법으로 픽셀 값 변경하기

OpenCV에서 픽셀 값을 다룰 때 앞서 살펴본 'at' 메서드는 픽셀 값에 접근할 때마다 이미지 타입을 일일이 지정해야 한다는 번거로움이 있습니다. 이보다 더 간단하고 직관적인 대안이 바로 직접 접근(Direct Access) 방법입니다.

직접 접근 방법을 사용하려면 Mat<uchar>, Mat<Vec3b>, Mat<Vec2i>와 같이 Mat 타입을 미리 구체적으로 지정해야 합니다. 타입을 지정한 후에는 배열을 다루듯 image(j, i) 형태로 행과 열 인덱스를 사용하여 해당 위치의 픽셀 값에 곧바로 접근하거나 수정할 수 있습니다.

다음 예제 프로그램은 OpenCV에서 직접 접근 방법을 활용해 픽셀 값을 변경하는 과정을 보여줍니다. 무작위로 선택한 4,000개의 픽셀을 0(검정색)으로 설정하여 노이즈가 섞인 이미지를 만들어 냅니다.

예제 코드

#include<iostream>
#include<opencv2/highgui/highgui.hpp>
using namespace cv;//cv 네임스페이스 선언//
using namespace std;
void direct_access(Mat_<Vec3b> &image, int n){ //direct_access 함수 선언//
   for (int x = 0; x < n; x++){ //for 루프 실행//
      int i = rand() % image.cols;//무작위 열(column) 좌표 생성//
      int j = rand() % image.rows;//무작위 행(row) 좌표 생성//
      image(j, i) = 0;//해당 픽셀 값을 0으로 설정//
   }
}
int main() {
   Mat_<Vec3b> image;//이미지 행렬 선언//
   Mat unchanged_Image;//원본 비교용 이미지 행렬 선언//
   image = imread("sky.jpg");//이미지 불러오기//
   unchanged_Image = imread("sky.jpg");//동일한 이미지 불러오기//
   namedWindow("Noisy Image");//윈도우 생성//
   namedWindow("Unchanged Image");//비교용 윈도우 생성//
   direct_access(image, 4000);//직접 접근 함수 호출//
   imshow("Noisy Image", image);//노이즈가 적용된 이미지 표시//
   imshow("Unchanged Image", unchanged_Image);//원본 이미지 표시//
   waitKey(0);//키 입력 대기//
   return 0;
}

코드 핵심 포인트

예제 코드의 동작 원리를 이해하기 위해 주요 부분을 정리하면 다음과 같습니다.

  • Mat_<Vec3b> : BGR 3채널 컬러 이미지를 저장하기 위한 Mat 타입입니다. Vec3b는 각 채널이 uchar(0~255) 값 3개(B, G, R)로 구성됨을 의미합니다.
  • rand() % image.cols / rand() % image.rows : 이미지 크기 범위 내에서 무작위 열과 행 좌표를 생성합니다.
  • image(j, i) = 0 : j번째 행, i번째 열에 위치한 픽셀 값을 0으로 설정합니다. 컬러 이미지에서는 세 채널이 모두 0이 되어 해당 픽셀이 검정색으로 표시되며, 이것이 반복되면 소금-후추(salt-and-pepper) 노이즈와 유사한 효과가 나타납니다.
  • imshow() : 노이즈가 적용된 이미지와 원본 이미지를 나란히 출력하여 두 결과를 시각적으로 비교할 수 있게 해줍니다.

실행 결과

OpenCV 직접 접근(Direct Access) 방법으로 픽셀 값 변경하기

실행 결과를 보면 왼쪽의 노이즈 이미지는 무작위로 선택된 픽셀들이 검정색으로 바뀌어 점점이 흩어져 있는 반면, 오른쪽의 원본 이미지는 그대로 유지되는 것을 확인할 수 있습니다. 이처럼 직접 접근 방법을 사용하면 'at' 메서드보다 코드가 간결해지고, 마치 2차원 배열을 다루는 것처럼 자연스럽게 픽셀 단위 연산을 수행할 수 있습니다.