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

JavaとOpenCVで画像の輪郭(コンタ)を検出する方法【findContours()徹底解説】

輪郭(コンタ)とは、特定の形状の境界線上にあるすべての点を結んだ線のことです。輪郭を検出することで、以下のような処理が可能になります。

  • 物体の形状を把握する
  • 物体の面積を計算する
  • 物体を検出する
  • 物体を認識する

findContours()メソッドとは

OpenCVでは、findContours()メソッドを使うことで、画像内に含まれるさまざまな形状や物体の輪郭を検出できます。このメソッドは、以下のパラメータを受け取ります。

  • 二値化された画像
  • 検出した輪郭を格納するための、MatOfPoint型の空のリストオブジェクト
  • 画像のトポロジー(階層情報)を格納するための空のMatオブジェクト
  • 輪郭検出のモードと手法を指定する2つの整数値

サンプルコード

以下は、JavaでOpenCVを使用して画像から輪郭を検出する具体的な実装例です。まず画像を読み込み、グレースケール変換と二値化を行った上で、findContours()メソッドを呼び出しています。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class FindingContours {
    public static void main(String args[]) throws Exception {
        // OpenCVのコアライブラリを読み込む
        System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
        String file = "D:\\Images\\shapes.jpg";
        Mat src = Imgcodecs.imread(file);

        // ソース画像をグレースケールに変換し、二値化する
        Mat gray = new Mat(src.rows(), src.cols(), src.type());
        Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
        Mat binary = new Mat(src.rows(), src.cols(), src.type(), new Scalar(0));
        Imgproc.threshold(gray, binary, 100, 255, Imgproc.THRESH_BINARY_INV);

        // 輪郭を検出する
        List<MatOfPoint> contours = new ArrayList<>();
        Mat hierarchey = new Mat();
        Imgproc.findContours(binary, contours, hierarchey,
            Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);

        // 検出された輪郭を出力する
        Iterator<MatOfPoint> it = contours.iterator();
        while(it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

実行結果

このプログラムを実行すると、検出された各輪郭がMatオブジェクトとして標準出力に表示されます。各行は1つの輪郭を表しており、「29*1*CV_32SC2」のような形式で、その輪郭を構成する点の数などの情報が確認できます。

Mat [ 29*1*CV_32SC2, isCont=true, isSubmat=false, nativeObj=0x19829510,
dataAddr=0x19826dc0 ]
Mat [ 58*1*CV_32SC2, isCont=true, isSubmat=false, nativeObj=0x19829580,
dataAddr=0x19826f00 ]
Mat [ 35*1*CV_32SC2, isCont=true, isSubmat=false, nativeObj=0x19828be0,
dataAddr=0x19827100 ]
Mat [ 117*1*CV_32SC2, isCont=true, isSubmat=false, nativeObj=0x19829190,
dataAddr=0x19827280 ]
Mat [ 1*1*CV_32SC2, isCont=true, isSubmat=false, nativeObj=0x198292e0,
dataAddr=0xba8280 ]
Mat [ 78*1*CV_32SC2, isCont=true, isSubmat=false, nativeObj=0x19829350,
dataAddr=0x19827680 ]
Mat [ 63*1*CV_32SC2, isCont=true, isSubmat=false, nativeObj=0x198289b0,
dataAddr=0x19827940 ]
Mat [ 120*1*CV_32SC2, isCont=true, isSubmat=false, nativeObj=0x19828e80,
dataAddr=0x19827b80 ]
Mat [ 4*1*CV_32SC2, isCont=true, isSubmat=false, nativeObj=0x19829430,
dataAddr=0xb84580 ]
Mat [ 4*1*CV_32SC2, isCont=true, isSubmat=false, nativeObj=0x19829120,
dataAddr=0xb84440 ]
Mat [ 136*1*CV_32SC2, isCont=true, isSubmat=false, nativeObj=0x19828ef0,
dataAddr=0x19827f80 ]
Mat [ 120*1*CV_32SC2, isCont=true, isSubmat=false, nativeObj=0x19828b00,
dataAddr=0x19828440 ]

補足:輪郭の描画について

検出した輪郭を視覚的に確認したい場合は、コメントアウトされているコードのようにdrawContours()メソッドを使用します。このメソッドに輪郭リスト・インデックス・色などを指定することで、検出結果を画像上に描画できます。また、HighGuiクラスのimshow()メソッドを使えば、描画結果をウィンドウ上に表示して確認することも可能です。

  1. JavaのOpenCVライブラリでカラー画像をグレースケールに変換する方法

    カラー画像をグレースケールに変換する基本OpenCVのImgprocクラスが提供するcvtColor()メソッドを使うと、画像の色空間を別の色空間へ変換できます。このメソッドは以下の3つのパラメータを受け取ります。src – 変換元の画像を表すMatオブジェクト(ソース)dst – 変換結果を格納するMatオブジェクト(出力先)code – 変換後の色空間を指定する整数値(カラーコード)カラー画像をグレースケールに変換する場合は、第3パラメータにImgproc.COLOR_RGB2GRAYを指定します。このコードはRGB形式の画像をグレースケール(白黒の濃淡表現)へ変換することを意味しています

  2. JavaとOpenCVライブラリを使って画像を保存(書き出し)する方法

    OpenCVライブラリを利用すると、画像フィルタリング、幾何学的変換、色空間の変換、ヒストグラム処理など、さまざまな画像処理操作を行うことができます。本記事では、その中でも基本的な操作である「画像の読み込みと保存(書き出し)」の方法を解説します。画像を書き出す(保存する)方法Imgcodecsクラスのimread()メソッドを使って画像を読み込むと、その内容はMat(Matrix)オブジェクトに格納されます。読み込んだ画像をファイルとして保存するには、imwrite()メソッドを使用します。imwrite()メソッドは、以下の2つの引数を受け取ります。file:保存先のファイルパスを表す文字列