Java
 Computer >> コンピューター >  >> プログラミング >> Java

【Java×OpenCV】大津の二値化(Otsu法)の使い方をサンプルコードで解説

閾値処理(しきい値処理)は、画像をセグメンテーション(領域分割)するためのシンプルな手法の一つで、二値画像を作成する際によく利用されます。この処理では、指定した閾値よりも大きい画素値が、あらかじめ定めた標準値に置き換えられます。

閾値処理の主な種類

  • 単純閾値処理(Simple Thresholding):画像全体に対して1つの固定された閾値を適用します。
  • 適応的閾値処理(Adaptive Thresholding):画像を小さな領域に分け、それぞれの領域ごとに閾値を計算します。そのため、領域によって異なる閾値が使用されます。

一方、大津の二値化(Otsu法)では、閾値が自動的に決定されます。画像のヒストグラムを解析し、最適な閾値を自動的に選択するのが特徴です。

threshold() メソッドの基本

OpenCVの Imgproc クラスが提供する threshold() メソッドは、以下の引数を受け取ります。

  • 入力画像と出力画像を表す2つのMatオブジェクト
  • 閾値および標準値を表す2つの整数値
  • 閾値処理の種類を表す整数値

これらのパラメータを渡してメソッドを呼び出すと、指定した画像に対して閾値処理が実行され、その結果が出力用のMatオブジェクトに格納されます。

大津の二値化を適用したい場合は、処理の種類として Imgproc.THRESH_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を作成
        Mat dst = new Mat(src.rows(), src.cols(), src.type());
        // 大津の二値化を適用
        Imgproc.threshold(src, dst, 50, 255, Imgproc.THRESH_OTSU);
        // MatをJavaFXのWritableImageに変換
        Image img = HighGui.toBufferedImage(dst);
        WritableImage writableImage = SwingFXUtils.toFXImage((BufferedImage) img, null);
        // ImageViewの設定
        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);
    }
}

コードのポイント

  • Imgcodecs.imread()IMREAD_GRAYSCALE フラグ付きで呼び出し、画像をグレースケールとして読み込んでいます。大津の二値化はグレースケール画像に対して適用する必要があります。
  • threshold() の第5引数に Imgproc.THRESH_OTSU を渡すことで、閾値が自動的に計算されます。第3引数の「50」は大津法では初期候補として扱われるため、厳密な値である必要はありません。
  • 処理結果はJavaFXのImageViewを通じてウィンドウ上に表示されます。

入力画像

【Java×OpenCV】大津の二値化(Otsu法)の使い方をサンプルコードで解説

実行結果

【Java×OpenCV】大津の二値化(Otsu法)の使い方をサンプルコードで解説

このように、大津の二値化を利用すれば、閾値を手動で調整することなく、画像の特性に応じた最適な二値化を簡単に実現できます。明暗差がはっきりした文書画像や物体検出の前処理など、さまざまな場面で活用できる強力な手法です。

  1. OpenCVとJavaFXで画像の明るさを下げる方法:convertTo()メソッドの実装例

    Javaで画像の明るさを変更する方法の一つとして、OpenCVのconvertTo()メソッドを使う手法があります。このメソッドは、指定された行列(Mat)に対して必要な計算を実行し、画像のコントラストや明るさを調整します。convertTo()メソッドは以下の4つのパラメータを受け取ります。mat − 結果を格納するための空の行列。元の行列と同じサイズ・型である必要があります。rtype − 出力行列の型を指定する整数値。負の値を指定した場合、出力行列の型は元の行列と同じになります。alpha − ゲイン値。0より大きい値である必要があります(デフォルト値は1)。beta − バイアス値(デ

  2. JavaとOpenCVライブラリを使って画像内の顔を検出する方法

    JavaでOpenCVを使用して画像から顔を検出するには、CascadeClassifierクラスを利用します。このクラスは、分類器ファイル(カスケードファイル)を読み込み、画像内から目的のオブジェクト(ここでは顔)を検出する役割を担います。 CascadeClassifierクラスとは CascadeClassifierは、OpenCVが提供する物体検出用のクラスです。事前に学習済みのカスケード分類器(XMLファイル)を読み込むことで、顔や人など特定のパターンを画像から認識できます。 detectMultiScale()メソッドについて このクラスが持つdetectMultiScale(