質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.74%

  • Java

    13122questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Eclipse

    1599questions

    Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

  • OpenCV

    963questions

    OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

BFMatcherクラスのマッチングのメソッドでunknown exceptionエラーが表示します

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 197

oka_99

score 3

 前提・実現したいこと

JAVA/OpenCVを用いて2枚の画像の特徴点マッチングのプログラムを書いています。
2枚の画像の特徴点を抽出するところまでは来たのですが
マッチングクラスのマッチングメソッドで必ずunknown exceptionのエラーが表示します。。
コード的に問題があるところをご指摘いただけたら助かります。

 発生している問題・エラーメッセージ

必ずmatch()メソッドを実行するタイミングで以下のエラーが表示されます。

Exception in thread "main" java.lang.Exception: unknown exception
    at org.opencv.features2d.DescriptorMatcher.match_1(Native Method)
    at org.opencv.features2d.DescriptorMatcher.match(DescriptorMatcher.java:223)
    at opencv_test1.ImgConv.main(ImgConv.java:63)
[ INFO:0] Initialize OpenCL runtime...

 該当のソースコード

package opencv_test1;


import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfDMatch;
import org.opencv.core.MatOfKeyPoint;
import org.opencv.features2d.BFMatcher;
import org.opencv.features2d.Features2d;
import org.opencv.features2d.ORB;
import org.opencv.imgcodecs.Imgcodecs;

//--------------------------------------------------------------
//画像処理 特徴点の抽出 特徴点同士のマッチング
//--------------------------------------------------------------
public class ImgConv{

    public static void main(String[] args) {

        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        Mat              im_src1;                           //元画像1(グレイスケール)
        Mat              im_src2;                           //元画像2(グレイスケール)
        MatOfKeyPoint    my_keypoints1;                     //特徴点の位置やパラメータを保存する変数
        MatOfKeyPoint    my_keypoints2;                     //特徴点の位置やパラメータを保存する変数
        Mat              my_descriptors1;                    //特徴量
        Mat              my_descriptors2;                    //特徴量

        ORB              my_orb;                            //特徴点抽出クラス

        my_orb = ORB.create();

    //1枚目の画像から特徴点を抽出
        im_src1 = Imgcodecs.imread("C:\\WORK\\20180411\\img_grayscale\\DSC_0021.jpg");    //作業ファイルの読み込み
        my_keypoints1 = new MatOfKeyPoint();
        my_descriptors1 = new Mat();

        my_orb.detect(im_src1, my_keypoints1);                                // 特徴点抽出処理
        my_orb.compute(im_src1, my_keypoints1, my_descriptors1);

    //2枚目の画像から特徴点を抽出
        im_src2 = Imgcodecs.imread("C:\\WORK\\20180411\\img_grayscale\\DSC_0022.jpg");    //作業ファイルの読み込み
        my_keypoints2 = new MatOfKeyPoint();
        my_descriptors2 = new Mat();

        my_orb.detect(im_src2, my_keypoints2);                                // 特徴点抽出処理
        my_orb.compute(im_src2, my_keypoints2, my_descriptors2);

    //特徴点の対応を調べる
        BFMatcher matcher = new BFMatcher(NORM_HAMMING,true);        //特徴点の対応を調べるクラス
        MatOfDMatch result_matches = new MatOfDMatch();            //マッチング結果保存用行列

    result_matches.create(my_descriptors1.rows(), my_descriptors1.cols(),my_descriptors1.type());        //出力先の型を決める?        //特徴点のマッチング
        matcher.match(my_descriptors1, my_descriptors2, result_matches);<<<<<ここで必ずエラーが発生します**

    //新規画像を作成し結果をファイルに書き込み
    Mat outImg = new Mat();                                    //結果画像保存用行列
        Features2d.drawMatches(my_descriptors1, my_keypoints1, my_descriptors2, my_keypoints2, result_matches, outImg);    //結果をデータ化
        Imgcodecs.imwrite("C:\\WORK\\20180411\\find_feature_points\\result.jpg", outImg);                                //書き込み

    //後処理
        im_src1.release();
        im_src2.release();
    outImg.release();

    }
}

 試したこと

1)それぞれの画像から特徴点を抽出できているか→それぞれの画像にデータを書き込むことで正常に動作していることと確認。
→my_descriptors1,my_descriptors2ともどもデータは保存されています。

2)match()メソッドをコメントしてプログラムを実行すると結果の書き込み部分Features2d.drawMatchesを実行し画像が結合して出力しているので画像だけの部分に関してはコード自体は正しい?と思っています。

3)問題は、matcher.match(my_descriptors1, my_descriptors2, result_matches);で必ず例外エラーが発生することです。

Exception in thread "main" java.lang.Exception: unknown exception
at org.opencv.features2d.DescriptorMatcher.match_1(Native Method)
at org.opencv.features2d.DescriptorMatcher.match(DescriptorMatcher.java:223)
at opencv_test1.ImgConv.main(ImgConv.java:63)
[ INFO:0] Initialize OpenCL runtime...

ドキュメントやプログラムサイトをみると基本的な流れは
1)ORBクラスでの特徴点検出
2)ORBクラスでつくった特徴点データはNORM_HAMMING/相互確認はTRUEでマッチャーを作成し、match()メソッドを呼ぶ
→matchメソッドのパラメータのMatOfDMatchにマッチング結果が保存される

ということだと理解しています。

デバッカーで追ってみましたがmatch()メソッドは
public  void match(Mat queryDescriptors, Mat trainDescriptors, MatOfDMatch matches)
と定義されていますが、以下パラメータ
Mat queryDescriptors
Mat trainDescriptors
MatOfDMatch matches
とも、デバッカで中身をみるとnativeOBJ変数の値があり、計算処理に渡すメモリの保持はしているみたいです。

2018/04/20追加
opencvのパッケージの中の
\opencv\sources\modules\calib3d\test\test_homography.cpp
に同じ内容をC++で書いたコードがあります。
Step3までが同じ内容ですのでこれを自分の環境で動作するか確認するしかないでしょうか...

TEST(Calib3d_Homography, fromImages)
{
Mat img_1 = imread(cvtest::TS::ptr()->get_data_path() + "cv/optflow/image1.png", 0);
Mat img_2 = imread(cvtest::TS::ptr()->get_data_path() + "cv/optflow/image2.png", 0);

Ptr<ORB> orb = ORB::create();
vector<KeyPoint> keypoints_1, keypoints_2;
Mat descriptors_1, descriptors_2;
orb->detectAndCompute( img_1, Mat(), keypoints_1, descriptors_1, false );
orb->detectAndCompute( img_2, Mat(), keypoints_2, descriptors_2, false );

//-- Step 3: Matching descriptor vectors using Brute Force matcher
BFMatcher  matcher(NORM_HAMMING,false);
std::vector< DMatch > matches;
matcher.match( descriptors_1, descriptors_2, matches );     <<<<ここで落ちるか確認
++++++++ここから先のコードは関連がないので割愛します    

}

 補足情報(FW/ツールのバージョンなど)

OpenCV 3.41
JAVA version10
Eclipse Oxygen.2 Release (4.7.2)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

Exception in thread "main" java.lang.Exception: unknown exception

BFMatcher

Brute-force matcher constructor (obsolete). Please use BFMatcher.create()

◇適当和訳
ブルートフォースマッチャーコンストラクター(廃止)。 BFMatcher.create()を使用してください

よって原因は以下の行です。

BFMatcher matcher = new BFMatcher(DescriptorMatcher.BRUTEFORCE_HAMMING, true);


import org.opencv.features2d.DescriptorMatcher;

DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);


もしくは以下のように修正してください。

BFMatcher matcher = BFMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING, true);
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfDMatch;
import org.opencv.core.MatOfKeyPoint;
import org.opencv.features2d.BFMatcher;
import org.opencv.features2d.DescriptorMatcher;
import org.opencv.features2d.Features2d;
import org.opencv.features2d.ORB;
import org.opencv.imgcodecs.Imgcodecs;

public class ImgConv {
    static {
        // opencvのライブラリを読み込む
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    public static void main(String[] args) {
        final String base_path = "C:\\z\\";

        // 元画像1と2を読み込み、Mat配列に格納
        Mat[] images = { loadImage(base_path + "DSC_0021.jpg"), loadImage(base_path + "DSC_0022.jpg") };
        ORB my_orb = ORB.create(); // 特徴点抽出クラス

        MatOfKeyPoint[] keypoints = new MatOfKeyPoint[images.length];
        Mat[] descriptors = new Mat[images.length];
        for (int i = 0; i < images.length; i++) {
            keypoints[i] = new MatOfKeyPoint();
            descriptors[i] = new Mat();
            my_orb.detect(images[i], keypoints[i]);
            my_orb.compute(images[i], keypoints[i], descriptors[i]);
        }

        // 特徴点の対応を調べる
        MatOfDMatch result_matches = match(descriptors);
        Mat outImg = new Mat(); // 結果画像保存用行列
        // 引数を変更
        Features2d.drawMatches(images[0], keypoints[0], images[1], keypoints[1], result_matches, outImg); // 結果をデータ化
        // Features2d.drawMatches(my_descriptors1, my_keypoints1, my_descriptors2,
        // my_keypoints2, result_matches, outImg); //結果をデータ化
        Imgcodecs.imwrite(base_path + "result.jpg", outImg); // 書き込み

        // 後処理
        release(images);
        release(new Mat[] { outImg });
    }

    public static Mat loadImage(String path) {
        // Mat src = Imgcodecs.imread(path);
        // ※グレースケールで読み込むなら以下の行でも。
        Mat src = Imgcodecs.imread(path, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
        if (src.empty()) {
            // ファイルが読み込めなかった時
            throw new RuntimeException(path);
        }
        return src;
    }

    public static MatOfDMatch match(Mat[] descriptors) {
        DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
        // DescriptorMatcher matcher = new
        // BFMatcher(DescriptorMatcher.BRUTEFORCE_HAMMING, true); // 特徴点の対応を調べるクラス
        MatOfDMatch result_matches = new MatOfDMatch(); // マッチング結果保存用行列
        // ※↓の行はC++の公式サンプルには存在しませんが、どこのサンプルに記述されてましたか?
        // result_matches.create(descriptors[0].rows(),
        // descriptors[0].cols(),descriptors[0].type());
        // 特徴点のマッチング
        matcher.match(descriptors[0], descriptors[1], result_matches);
        return result_matches;
    }

    public static void release(Mat[] images) {
        for (Mat m : images) {
            m.release();
        }
    }
}


勝手ながらソースを改造しました。

1,変数は先頭でまとめて宣言せずに適切な値で初期化するように。
2,ファイルが存在しない時にImgcodecs.imreadの戻り値のMatオブジェクトがemptyで無いかをチェックし例外を発生させるように(loadImageメソッド)。
Imgcodecs.imreadは画像が読み取れなかった時に例外を発生せず、後続の処理で例外が発生します。
3,detectcomputeを連続して行うなら、Feature2D#detectAndComputeが使えます。
→上記ソースでは未対応
4,imageskeypointsdescriptorsは配列で管理するように。
5,imwriteの書き出しパスを入力ファイルと同一パスに。
6,matchメソッドとreleaseメソッドを追加

◇参考情報
cv::BFMatcher::BFMatcher

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/23 16:38

    umyuさん:
    どうもご指摘ありがとうございます。
    BFMatcherの初期化に問題があるとのご指摘と
    コードに対してもご指摘どうもありがとうございます。
    書き直しているのですが
    ご指摘どおりcreate()に変更しましたがまだ別途エラーがでているので
    画像データ自体も問題があるのか検討しています。
    ちゃんと動作確認してから再度コメントさせていただきます。
    どうもありがとうございます。

    キャンセル

  • 2018/04/23 17:16

    >oka_99さんへ
    matcher.matchでは質問文のエラーが発生しなくなったと認識してもよいでしょうか?
    あと考えられる事としては、
    1,Lena画像で問題が再現するかどうかを確かめて見た方がよいかと。
    2,画像のファイルパスを日本語を含まない形にしても再現するかどうか。
    3,OpenCVのライブラリのバージョンを落として、問題が再現するかどうか。
    こういう点でしょうか。

    キャンセル

  • 2018/04/24 12:48

    umyuさん:
    どうもありがとうございます。
    クラス/メソッドの変更だけのみを試しましたらば
    match()でunknown...のエラーは表示しなくなりましたが別のエラーが表示されています。
    umyuさんの書いていただいた全体のコードで試したところ
    こちらでは問題が出ませんでした。
    やはり自分のコードに問題/見落としがあるのだと思います。
    もうちょっとコードを分析をします。
    自分のレスポンスが遅れがちななか、どうもありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.74%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Java

    13122questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Eclipse

    1599questions

    Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

  • OpenCV

    963questions

    OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。