임계값 처리(Thresholding)란?
임계값 처리는 이미지 분할(Segmentation)을 수행하는 가장 간단한 기법 중 하나로, 주로 이진화(Binary) 이미지를 생성하는 데 사용됩니다. 이 기법에서는 지정된 임계값보다 큰 픽셀이 미리 정해진 표준 값으로 대체됩니다.
- 단순 임계값(Simple Thresholding): 하나의 임계값이 이미지 전체에 동일하게 적용됩니다.
- 적응형 임계값(Adaptive Thresholding): 작은 영역 단위로 임계값을 계산하기 때문에 영역마다 서로 다른 임계값이 적용됩니다.
반면 Otsu 임계값(Otsu's Thresholding) 기법은 임계값을 개발자가 직접 지정할 필요가 없습니다. 이미지의 히스토그램을 분석하여 전경과 배경 두 그룹 사이의 클래스 내 분산을 최소화하는 최적의 임계값을 자동으로 결정합니다. 덕분에 조명 상태가 일정하지 않거나 적절한 임계값을 미리 예측하기 어려운 이미지에서도 우수한 결과를 얻을 수 있습니다.
threshold() 메서드의 매개변수
OpenCV의 Imgproc 클래스가 제공하는 threshold() 메서드는 다음과 같은 매개변수를 받습니다.
- 원본(소스) 이미지와 결과(대상) 이미지를 나타내는 두 개의
Mat객체 - 임계값과 표준 값(maxval)을 나타내는 두 개의 정수 변수
- 적용할 임계값 처리 유형을 나타내는 정수 변수
메서드가 호출되면 지정된 이미지에 임계값 연산을 수행하고, 그 결과를 대상 행렬(dst)에 저장합니다.
Otsu 기법을 적용하려면 threshold() 메서드를 호출할 때 유형 매개변수에 Imgproc.THRESH_OTSU를 전달하면 됩니다. 참고로 Otsu 플래그를 사용하면 임계값으로 전달한 값은 무시되며, 히스토그램으로부터 자동 계산된 최적 값이 대신 사용됩니다.
예제 코드
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.stage.Stage;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class OtsuThresholding extends Application {
public void start(Stage stage) throws IOException {
// OpenCV 네이티브 핵심 라이브러리 로드
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
String file = "D:\\Images\\win2.jpg";
// 이미지를 그레이스케일로 읽어오기
Mat src = Imgcodecs.imread(file, Imgcodecs.IMREAD_GRAYSCALE);
// 결과 이미지를 저장할 빈 행렬 생성
Mat dst = new Mat(src.rows(), src.cols(), src.type());
// Otsu 임계값 적용
Imgproc.threshold(src, dst, 50, 255, Imgproc.THRESH_OTSU);
// 행렬을 JavaFX용 이미지로 변환
Image img = HighGui.toBufferedImage(dst);
WritableImage writableImage = SwingFXUtils.toFXImage((BufferedImage) img, null);
// 이미지 뷰 설정
ImageView imageView = new ImageView(writableImage);
imageView.setX(10);
imageView.setY(10);
imageView.setFitWidth(575);
imageView.setPreserveRatio(true);
// Scene 객체 설정
Group root = new Group(imageView);
Scene scene = new Scene(root, 595, 400);
stage.setTitle("Otsu Threshold");
stage.setScene(scene);
stage.show();
}
public static void main(String args[]) {
launch(args);
}
}
위 예제는 이미지를 IMREAD_GRAYSCALE 옵션으로 그레이스케일로 불러온 뒤, THRESH_OTSU 플래그를 사용해 Otsu 임계값을 적용하고, 처리된 결과를 JavaFX 윈도우에 화면에 출력하는 전체 과정을 보여줍니다.
입력 이미지

출력 결과
