【Java×OpenCV】キャニーエッジ検出の実装方法をサンプルコード付きで解説
キャニーエッジ検出器(Canny Edge Detector)は、最も優れたエッジ検出手法の一つとして知られています。次の3つの基準を満たすため、「最適な検出器」と呼ばれています。
- 実際に存在するエッジのみを検出する
- 1つのエッジに対して1つの応答のみを返す
- エッジピクセルと検出されたピクセル間の距離を最小化する
OpenCVでは、ImgprocクラスのCanny()メソッドを使用することで、指定した画像にキャニーエッジ検出アルゴリズムを適用できます。このメソッドは、以下の引数を受け取ります。
- ソース画像と出力先画像を表す2つのMatオブジェクト
- 閾値(しきいち)を保持する2つのdouble型変数
2つの閾値はヒステリシス閾値と呼ばれ、第1引数が下限閾値、第2引数が上限閾値です。勾配が上限を超える画素は強いエッジとして採用され、下限と上限の間にある画素は周囲との連結性によって判定されます。
キャニーエッジ検出の基本的な手順
キャニーエッジ検出器を使って画像のエッジを検出するには、一般的に以下の手順に従います。
- Imgcodecsクラスのimread()メソッドで、ソース画像を読み込みます。
- ImgprocクラスのcvtColor()メソッドで、画像をグレースケールに変換します。
- blur()メソッドでカーネルサイズ3を指定し、グレースケール画像にぼかし(ノイズ除去)をかけます。
- ImgprocクラスのCanny()メソッドで、ぼかした画像にキャニーエッジ検出アルゴリズムを適用します。
- すべての値が0の空のマトリックスを作成します。
- MatクラスのcopyTo()メソッドで、検出されたエッジを出力先のマトリックスへコピーします。
サンプルコード
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.core.Scalar;
import org.opencv.core.Size;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class EdgeDetection 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);
// エッジ・ソース・出力先を格納する空のマトリックスを作成
Mat gray = new Mat(src.rows(), src.cols(), src.type());
Mat edges = new Mat(src.rows(), src.cols(), src.type());
Mat dst = new Mat(src.rows(), src.cols(), src.type(), new Scalar(0));
// 画像をグレースケールに変換
Imgproc.cvtColor(src, gray, Imgproc.COLOR_RGB2GRAY);
// 画像にぼかしをかける
Imgproc.blur(gray, edges, new Size(3, 3));
// エッジを検出する
Imgproc.Canny(edges, edges, 100, 100*3);
// 検出されたエッジを出力先のマトリックスにコピー
src.copyTo(dst, edges);
// マトリックスを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("Canny Edge Detection Example");
stage.setScene(scene);
stage.show();
}
public static void main(String args[]) {
launch(args);
}
}このコードでは、下限閾値を100、上限閾値を300(100×3)に設定しています。閾値の比率は一般的に2:1〜3:1程度が推奨されており、値を調整することで検出されるエッジの量を制御できます。
入力画像

実行結果
上記のプログラムを実行すると、次のような出力が得られます。

元画像から輪郭となるエッジ部分だけが白く抽出され、それ以外の領域は黒くなっていることが確認できます。これにより、物体の形状や輪郭を効率的に捉えることが可能になります。
-
JavaとOpenCVでガウシアンブラー(ガウスぼかし)を実装する方法を徹底解説
画像にローパスフィルタを適用してフィルタリングを行うことで、画像をぼかすことができます。この処理により、ノイズやエッジといった高周波成分が画像から取り除かれます。ガウシアンブラー(Gaussian Blurring:ガウスぼかし)は、OpenCVが提供するぼかし手法のひとつで、画像のノイズ除去に非常に高い効果を発揮します。この手法では、カーネル領域内のすべてのピクセルの平均値を使って、中心の要素を置き換えます。GaussianBlur()メソッドの使い方この手法で画像をフィルタリング・ぼかし処理するには、GaussianBlur()メソッドを使用します。このメソッドは以下の引数を受け取ります。
-
JavaとOpenCVでブラー(平均化)フィルタを実装する方法を解説
画像にブラー(ぼかし)処理を加えるには、ローパスフィルタを使って画像をフィルタリングします。これにより、画像から高周波成分(ノイズやエッジなど)が除去されます。 平均化(Averaging)は、OpenCVが提供するぼかし手法のひとつです。カーネル領域内のすべてのピクセルの平均値を計算し、その値で中心のピクセルを置き換えることで、画像全体を滑らかにぼかします。 この手法で画像をフィルタリング・ぼかし処理するには、blur() メソッドまたは boxFilter() メソッドを使用します。blur() メソッドは、以下の引数を受け取ります。 ソース画像と出力先画像を表す2つの Mat オブジェ