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

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

新規登録して質問してみよう
ただいま回答率
85.50%
OpenCV

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

Java

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

Q&A

解決済

1回答

519閲覧

OpenCVのライブラリでcompute()メソッドのエラー

oka_99

総合スコア11

OpenCV

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

Java

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

0グッド

0クリップ

投稿2018/04/10 05:56

前提・実現したいこと

OpenCVのライブラリを利用して
java/eclipseを用いて画像の特徴点の抽出を実行しようとしています。

デバックを実行中、以下のエラーメッセージが発生しました。

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

Exception in thread "main" java.lang.NullPointerException
at org.opencv.features2d.Feature2D.compute(Feature2D.java:102)
at opencv_test1.ImgConv.main(ImgConv.java:36)
[ INFO:0] Initialize OpenCL runtime...

該当のソースコード

java

1package opencv_test1; 2 3import org.opencv.core.Core; 4import org.opencv.core.Mat; 5import org.opencv.core.MatOfKeyPoint; 6import org.opencv.features2d.Features2d; 7import org.opencv.features2d.ORB; 8import org.opencv.imgcodecs.Imgcodecs; 9 10//-------------------------------------------------------------- 11//画像処理 特徴点の抽出 12//-------------------------------------------------------------- 13public class ImgConv{ 14 15 16 public static void main(String[] args) { 17 18 MatOfKeyPoint my_keypoints1; //特徴点の位置やパラメータを保存する変数 19 Mat im_src; //元画像(グレイスケール) 20 Mat my_descriptors = null; //特徴量 21 ORB my_orb; 22 23 24 System.loadLibrary(Core.NATIVE_LIBRARY_NAME); //ライブラリのロード 25 26 im_src = Imgcodecs.imread("C:\WORK\20180328\img\squaregray.jpg"); //作業ファイルの読み込み 27 28 my_keypoints1 = new MatOfKeyPoint(); 29 30 my_orb = ORB.create(); 31 32 my_orb.detect(im_src, my_keypoints1); // 特徴点抽出処理 33 my_orb.compute(im_src, my_keypoints1, my_descriptors); 34 35 Features2d.drawKeypoints(im_src, my_keypoints1,my_descriptors );//画像への特徴点の書き込み 36 37 Imgcodecs.imwrite("C:\WORK\20180328\img\squaregray.jpg", my_descriptors);//処理後の画像の保存 38 39 im_src.release(); 40 41 } 42 43} 44 45

試したこと

デバックをすると
my_orb.compute(im_src, my_keypoints1, my_descriptors);
で呼び出されたOpenCVライブラリ内のFeature2D クラスメソッドの
public void compute(Mat image, MatOfKeyPoint keypoints, Mat descriptors)
{
Mat keypoints_mat = keypoints;
compute_0(nativeObj, image.nativeObj, keypoints_mat.nativeObj, descriptors.nativeObj);<<<<<ここで例外処理が起きています。
return;
}

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

環境
Oxygen.2 Release (4.7.2)
JavaSE*1.8

同じ環境で、OpenCVのライブラリの”画像に描画を実行する”メソッドは
正常に動作していますので、OpenCVのパスの設定が原因ではないと思っています。..

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YomogiKOBO

2018/04/10 06:01

> im_src = Imgcodecs.imread("C:\\WORK\\20180328\\img\\squaregray.jpg"); でのim_srcの値をデバッグして確認されていないということでしょうか。
oka_99

2018/04/10 06:04

squaregray.jpgの読み込みが正常に行われているか確認する必要があるということでしょうか?
YomogiKOBO

2018/04/10 06:08

my_orb.compute(im_src, my_keypoints1, my_descriptors);の引数に渡していますし、適切に値が渡されているかについて確認する必要があります。
oka_99

2018/04/10 06:28

ありがとうございます。もう一度データの確認をします。
YomogiKOBO

2018/04/10 06:58

気になったのは、my_descriptorsがnullでcomputeしてよかったんでしたっけ。
guest

回答1

0

ベストアンサー

NPEが発生したところまで突き止めておられますが、もう一歩踏み込んでNPEの原因を見ると原因にたどり着けただろうと思います。

###NPEの原因についてもう一歩踏み込んでみる
質問文にある通り実際に発生しているのはcomputeメソッドの内部にある以下の行ですが、

compute_0(nativeObj, image.nativeObj, keypoints_mat.nativeObj, descriptors.nativeObj);

第一引数ではNPEは起き得ません。これはAlgorithmクラスのフィールドですがその値がなんであろうとcompute_0メソッドにそのままわたるだけです。

よってNPEが起きる可能性があるのはimage, keypoints_mat, descriptorsのいずれかがnullの場合であることはこの行から明らかです。

さて、IDEを使ってデバッグすると便利な点はbreak pointを設定したりstep inしたりすることで、「その時点の変数の値」が確認できることです。それを最大限活用してデバッグしましょうcomputeを呼び出す行にbreak pointを設定してそこまで到達したらstep inしてみてください

そうすればdescriptorsがnullであることがわかると思います。それが分かったら今度はなぜそれがnullなのか原因をさかのぼりましょう。descriptorsはcomputeメソッドの第三引数に渡したものです。mainメソッドに戻ってそれが何かを確認すると第三引数はmy_descriptorsであり、それは変数宣言の際にnullを設定した以降何も設定してないことがわかります。

こうやって「どの値がまずかったのか」をさかのぼっていってください。

ここまでで、my_descriptorsがnullのままではいけないらしいことがわかります。

###対処

自分はOpenCVに暗いので対策としてどうするのが一番適切かはわかりません。想像できるのは「JavaラッパーではJavaオブジェクトにC++のオブジェクトのハンドル(アドレス)が記録されていてJavaからC++を呼び出す際にそのハンドルを介して情報をやりとりしているのだろう」という点だけです。

OpenCVのJavaDocを見てみましたが案の定computeメソッドの説明は空欄です。C++ライブラリーのラッパーだとこういうことはよくありますね。C++のAPIリファレンスもチラミしてみましたがその程度では当然ながらJava側でどう書くべきかはすぐに分かりません。本来ならばJavaラッパーの(必要に応じてC++ライブラリーのAPI仕様も)ドキュメントを一通り見て作法などを知る必要があるのだろうと思いますが、自分はそこまで詳しく見てないです。

自分の場合「とりあえずMatインスタンスを生成してそれ渡してみたら結果をそこに格納してくれるのではあるまいか」という非常に大雑把な推測をたてやってみました。

具体的にはcomputeを呼び出す直前で
my_descriptors = new Mat();
としてみました。

本件の場合はたまたまそれで期待動作してくれるみたいでした。対策方法を考える例としてはいささかよくない例ですがたまたまうまくいったということでご容赦を。

投稿2018/04/10 07:09

KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oka_99

2018/04/10 07:39

ああ、JAVAだと、インスタンスを生成して領域を確保してから メソッドに渡すことだったんですね! どうもありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問