마스크 연산(Mask Operation)의 기본 개념
마스크 연산은 주어진 마스크 행렬(커널, Kernel)을 기준으로 이미지의 각 픽셀 값을 다시 계산하는 과정을 말합니다. 이처럼 마스크를 이용해 이미지를 변환하는 작업은 필터링(Filtering)이라고도 부릅니다.
OpenCV의 Imgproc 클래스가 제공하는 filter2D() 메서드는 원본 이미지 행렬(src), 결과를 저장할 대상 행렬(dst), 그리고 커널 행렬(kernel)을 인자로 받아 원본 행렬과 커널 행렬 간의 합성곱(Convolution)을 수행합니다. 이 메서드를 활용하면 선명화, 블러 등 다양한 마스크 효과를 손쉽게 이미지에 적용할 수 있습니다.
filter2D() 메서드의 주요 파라미터
- src: 입력(원본) 이미지 행렬
- dst: 필터링 결과가 저장될 출력 행렬
- ddepth: 출력 이미지의 데이터 깊이 (-1이면 입력 이미지와 동일하게 지정)
- kernel: 필터링에 사용되는 커널(마스크) 행렬
예제 코드
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class MaskingExample {
public static void main( String[] args ) {
// OpenCV 네이티브 라이브러리 로드
System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
// 입력 이미지 읽기
String file = "D://images//boy.jpg";
Mat src = Imgcodecs.imread(file);
// 결과를 저장할 빈 행렬 생성
Mat dst = new Mat();
// 첫 번째 커널 생성 (선명화 필터)
Mat kernel1 = new Mat(3, 3, CvType.CV_8S);
int row = 0, col = 0;
kernel1.put(row, col, 0, -1, 0, -1, 5, -1, 0, -1, 0);
// 두 번째 커널 생성 (평균 블러 필터)
Mat kernel2 = Mat.ones(2,2, CvType.CV_32F);
for(int i = 0; i<kernel2.rows(); i++) {
for(int j = 0; j<kernel2.cols(); j++) {
double[] m = kernel2.get(i, j);
for(int k = 1; k<m.length; k++) {
m[k] = m[k]/(2 * 2);
}
kernel2.put(i,j, m);
}
}
// kernel1을 이용해 이미지 필터링
Imgproc.filter2D(src, dst, -1, kernel1);
HighGui.imshow("Mask Example1", dst);
dst = new Mat();
// kernel2를 이용해 이미지 필터링
Imgproc.filter2D(src, dst, -1, kernel2);
HighGui.imshow("Mask Example2", dst);
HighGui.waitKey();
}
}
예제 코드 설명
이 예제에서는 두 가지 서로 다른 커널을 사용합니다. 첫 번째 kernel1은 중심 값이 5이고 주변이 -1로 구성된 선명화(Sharpening) 필터로, 이미지의 윤곽과 디테일을 강조합니다. 두 번째 kernel2는 모든 요소가 같은 비율로 나뉜 평균(Averaging) 필터로, 이미지를 부드럽게 흐릿하게 만드는 블러 효과를 냅니다.
입력 이미지
예제에서 사용된 입력 이미지는 다음과 같습니다.

실행 결과
위 프로그램을 실행하면 각 커널이 적용된 결과 이미지가 담긴 두 개의 창이 순차적으로 표시됩니다.
Kernel1 적용 결과(선명화) − 
Kernel2 적용 결과(블러) − 
이처럼 커널 행렬의 값만 바꾸면 하나의 filter2D() 메서드만으로도 선명화, 블러, 엣지 검출 등 다양한 이미지 처리 효과를 구현할 수 있습니다.