본문 바로가기

프로그래밍 강좌/C++ - OpenCV

[OpenCV][C++] 영상 가장자리(Border) 픽셀 확장 방법 총정리 - 필터링 적용 copyMakeBorder

지난 시간에 평균 필터(Average Filter)에 대해 알아보면서 다루지 않은 부분이 있어요

바로 가장자리 픽셀 확장 방법에 대한 내용이에요.

cv::boxFilter()의 마지막 인자로 borderType이란 인자가 있었어요.

base.hpp를 보면, 아래와 같이 가장자리 타입 상수값들이 있어요.

제가 직접 실험해 본 결과를 적어봤습니다.

사실 BORDER_TRANSPARENT는 동작이 잘 안되는 것 같아요. 주석 기준으로 예측해본 거라 정확하지는 않습니다.

BORDER_ISOLATED도 사실 사용해본적이 없어서 잘 모르겠으나 값은 아래와 같이 나와서. 그냥 적은 것입니다. 확신이 없는 부분은 gray 색으로 적었습니다.

실제 결과를 보도록 하겠습니다.

배열 데이터를 생성합니다.

uchar data[] = { 1,2,3,4,5,6,
	             1,2,3,4,5,6,
	             1,2,3,4,5,6,
	             1,2,3,4,5,6,
	             1,2,3,4,5,6, 
	             1,2,3,4,5,6 };
 

위의 배열을 cv::Mat 으로 2차원 영상 형태로 변환합니다.

cv::Mat Data(6, 6, CV_8UC1, data);
 

가장자리를 패딩하는 함수 원형은 아래와 같습니다.

src
입력 영상
dst
출력 영상
top, bottom, left, right
상하좌우 패딩할 사이즈
borderType
가장자리 확장 방식
value
BORDER_CONSTANT 일 때 채울 값

 

copyMakeBorder를 사용하여 하나씩 영상을 만들어 볼께요.

상하좌우 3칸씩 패딩을 하는 소스입니다.

int border = 3;
cv::Mat A;
cv::copyMakeBorder(Data, A, border, border, border, border, cv::BORDER_CONSTANT, 0);

cv::Mat B;
cv::copyMakeBorder(Data, B, border, border, border, border, cv::BORDER_REPLICATE);

cv::Mat C;
cv::copyMakeBorder(Data, C, border, border, border, border, cv::BORDER_REFLECT);

cv::Mat D;
cv::copyMakeBorder(Data, D, border, border, border, border, cv::BORDER_WRAP);

cv::Mat E;
cv::copyMakeBorder(Data, E, border, border, border, border, cv::BORDER_REFLECT_101);

// copymakeborder 함수에서 사용할 수 없음
//cv::Mat F;
//cv::copyMakeBorder(Data, F, border, border, border, border, cv::BORDER_TRANSPARENT);

cv::Mat G;
cv::copyMakeBorder(Data, G, border, border, border, border, cv::BORDER_ISOLATED );
 

[입력 영상]

[BORDER_CONSTANT]

[BORDER_REPLICATE]

[BORDER_REFLECT]

[BORDER_WRAP]

[BORDER_REFLECT_101]

[BORDER_ISOLATE]

이 경계값 채우는 방법은 언제 사용될까요?

일반적으로 필터링 시 사용되고, 또는 영상 가장 자리에 일정 값으로 채우고 싶을 때 사용합니다.

cv::Mat src_color = cv::imread("lena_color.bmp", cv::IMREAD_COLOR);	
cv::Mat dst_color;
cv::copyMakeBorder(src_color, dst_color, 10, 10, 10, 10, cv::BORDER_CONSTANT,
                   cv::Scalar(255, 255, 0));
 

마치 영상 가장자리에 액자 같은 것을 씌워놓은 것 같죠?

또 이런 효과도 나타낼 수 있습니다.

그림 아래에 반사효과를 내고 싶다면, 아래처럼 하시면 됩니다.

cv::Mat src_ice = cv::imread("icecream.jpg");
cv::Mat dst_ice;
cv::copyMakeBorder(src_ice, dst_ice, 0, 20, 0, 0, cv::BORDER_REFLECT);