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

JavaとOpenCVで確率的ハフ変換(HoughLinesP)を使って画像から直線を検出する方法

確率的ハフ変換とは

ハフ変換(Hough Line Transform)は、画像の中から直線を検出するための代表的な手法です。OpenCVでは、標準ハフ変換(Standard Hough Line Transform)確率的ハフ変換(Probabilistic Hough Line Transform)の2種類が提供されています。標準ハフ変換が画像全体の直線を検出するのに対し、確率的ハフ変換は線分の両端の座標(始点・終点)を返すため、処理が高速で実用的な場面でよく使われます。

確率的ハフ変換を適用するには、ImgprocクラスのHoughLinesP()メソッドを使用します。このメソッドは主に以下のパラメータを受け取ります。

  • 入力画像(Matオブジェクト)と、検出された線分の情報を格納する出力用Matオブジェクト
  • r(ピクセル単位)およびΦ(ラジアン単位)の解像度を指定する2つのdouble型の値
  • 1本の線として「検出」するために必要な最小交差数(投票数の閾値)を表す整数値
  • さらに、最小線分長(minLineLength)と同一線上とみなす最大ギャップ(maxLineGap)も指定できます

サンプルコード

以下は、JavaでOpenCVの確率的ハフ変換を使って画像内の直線を検出するサンプルプログラムです。Canny法によるエッジ検出結果に対してHoughLinesP()を適用し、検出した線分を赤色で描画しています。

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.Point;
import org.opencv.core.Scalar;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class HoughLineProbabilisticTransform extends Application {
    public void start(Stage stage) throws IOException {
        // OpenCVのコアライブラリを読み込む
        System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
        String file ="D:\\Images\\road4.jpg";
        Mat src = Imgcodecs.imread(file);
        // 画像をグレースケールに変換
        Mat gray = new Mat();
        Imgproc.cvtColor(src, gray, Imgproc.COLOR_RGBA2GRAY);
        // エッジを検出
        Mat edges = new Mat();
        Imgproc.Canny(gray, edges, 60, 60*3, 3, false);
        // Canny結果の色空間を変更
        Mat cannyColor = new Mat();
        Imgproc.cvtColor(edges, cannyColor, Imgproc.COLOR_GRAY2BGR);
        // Canny結果からハフ変換で直線を検出
        Mat lines = new Mat();
        Imgproc.HoughLinesP(edges, lines, 1, Math.PI/180, 50, 50, 10);
        for (int i = 0; i < lines.rows(); i++) {
            double[] data = lines.get(i, 0);
            // 画像上に線分を描画
            Point pt1 = new Point(data[0], data[1]);
            Point pt2 = new Point(data[2], data[3]);
            Imgproc.line(cannyColor, pt1, pt2, new Scalar(0, 0, 255), 3);
        }
        // MatをJavaFXのWritableImageに変換
        Image img = HighGui.toBufferedImage(cannyColor);
        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("Hough Line Transform");
        stage.setScene(scene);
        stage.show();
    }
    public static void main(String args[]) {
        launch(args);
    }
}

入力画像

JavaとOpenCVで確率的ハフ変換(HoughLinesP)を使って画像から直線を検出する方法

実行結果

上記のプログラムを実行すると、次のような出力が得られます。道路の白線など、画像中の直線部分が赤い線分として検出されていることが確認できます。

JavaとOpenCVで確率的ハフ変換(HoughLinesP)を使って画像から直線を検出する方法

  1. JavaとOpenCVでバイラテラルフィルタ(バイラテラルブラー)を実装する方法

    画像にローパスフィルタを適用することでぼかし(ブラー)効果を得られます。ローパスフィルタは、画像から高周波成分(ノイズやエッジなど)を取り除く働きがあります。バイラテラルフィルタリングは、OpenCVが提供するぼかし処理の手法の一つで、次のような特徴を持っています。ノイズを効率的に除去できるエッジ(輪郭)をシャープなまま保持できる他のフィルタと比較して処理速度が遅いbilateralFilter() メソッドの使い方バイラテラルフィルタを画像に適用するには、bilateralFilter() メソッドを使用します。このメソッドは以下の引数を受け取ります。入力画像(ソース)と出力画像(デスティネ

  2. JavaとOpenCVで線を描画する方法をわかりやすく解説

    Java版OpenCVライブラリのorg.opencv.imgprocパッケージには、Imgprocというクラスが含まれています。画像に直線を描画するには、このクラスが提供するline()メソッドを呼び出します。 line()メソッドのパラメータ line()メソッドは、以下のパラメータを受け取ります。 Matオブジェクト ― 直線を描画する対象となる画像を表します。 Pointオブジェクト2つ ― 直線の始点と終点の座標を表します。 Scalarオブジェクト ― 直線の色をBGR形式で指定します。 整数値 ― 直線の太さを指定します(デフォルト値:1)。 サンプルコード 以下は、白紙の画