2012-03-29 5 views
7

O'Reillyによる「Learning OpenCV」という本はまだありません。それから私はOpenCVからJavaCVへのサンプルコードをすべて変換しています。自分自身の変更も。すべての中で、私は可能な限り純粋なOpenCV(C言語)コードを保ち、Javaを避けようとしています。たとえば、Java Swingではなく、JavaCVのOpenCV highguiパッケージを使用して、すべてのインタフェース要素を直接実装しました。これを行うことで、OpenCVライブラリといくつかのCを比較的短期間で習得し、後で純粋なOpenCVに切り替えることができれば、C言語に簡単に変換できる便利な関数ライブラリを構築することができます。OpenCV行列ループをJavaCVに変換する

とにかく、私はCの知識がほとんどなく、ポインタを扱うときにトラブルになることがあります。本は3チャネル行列を反復処理することにより、最適な手段として、次のコードをお勧めします:ここ

float sum(const CvMat* mat) { 
    float s = 0.0f; 
    for(int row=0; row<mat->rows; row++) { 
     const float* ptr = (const float*)(mat->data.ptr + row * mat->step); 
     for(col=0; col<mat->cols; col++) { 
      s += *ptr++; 
     } 
    } 
    return(s); 
} 

このコードのために含ま説明である:

マトリックスにポインタを計算する場合行列要素データ は共用体であることに注意してください。したがって、このポインタを参照解除するときは、正しいポインタ型を取得するために、ユニオンの正しい 要素を指定する必要があります。あなたは、 ポインタを設定するには、マトリックスのステップ要素を使用する必要があります。前述のように、ステップ 要素はバイト単位です。安全であるためには、バイト単位でポインタ演算を行い、次に適切な型にキャストしてください(この場合はfloat)。古いIplImage構造との互換性のために、CVMat構造体は高さと幅の概念を持っていますが、代わりに、より最新の行と列を使用します。最後に、単純に最初から始めてから、そのポインタをインクリメントするのではなく、すべての行に対して> ptrを再計算することに注意してください。 Thは多すぎると思われるかもしれませんが、CvMatデータポインタが大きいアレイ内のROIを指すようにすることができるため、データが連続して連続することは保証されません。

しかし、私はJavaCVに変換する際に問題があります。 ptrフィールド(ポインタ)は浮動小数点のようで、混乱します。私はそれが実際には 'ポインタ'ではなく、むしろ各ピクセルの値が加算される値であると推測します。または、実際にはポインタは、sの値が、指定された行の中のすべての列の総和を見つけますか?

誰かが等価なループのJavaCVコードを投稿してくれたら、とにかく感謝しています。私は、CvMatのすべてのピクセルにアクセスする他の方法があることを知っていますが、AFAIKはあまり効率的でないまたは不正確です。

+0

この例からわかるように、マトリックスは2次元、グレースケール、浮動小数点データ型として扱われます。すべてのピクセル値が合計され、sが累積輝度になります。 ptrは実際には任意の点で配列を指すポインタであり、 'ptr [x]'は '(const float *)(mat-> data.ptr + row * mat-> step)[x]と等しい。 '。 ptrは与えられたピクセルに対して初期化され、インクリメントされるので、 '[x]'は必要ではなく、 '[']、 '[0]'と単純に逆参照されます。 –

+0

@zomポインタはどのようにインクリメントされますか?私はコードの理解から、ポインタは、ピクセルの値が割り当てられていますか?または、ピクセルの位置が割り当てられていますか?前のケースでは、操作 'ptr ++'が発生した場合、ポインターが次のピクセルを指し示すのではなく、割り当てられたピクセル値が増加しませんか?そして、後者の場合、いつ、どこで、 's'に割り当てられたピクセルの実際の値がありますか?非常に多くの質問。 –

+0

これを最初に読んでください:http://c-faq.com/ptrs/index.html –

答えて

6

ここ

float sum(CvMat mat) { 
    final int rows = mat.rows(); 
    final int cols = mat.cols(); 
    final int step = mat.step()/4; 
    FloatBuffer buf = mat.getFloatBuffer(); 
    float s = 0.0f; 
    for (int row = 0; row < rows; row++) { 
     buf.position(row * step); 
     for (int col = 0; col< cols; col++) { 
      s += buf.get(); 
     } 
    } 
    return s; 
} 
+0

サム、JavaCV自身の開発者からの回答を得るのはいいですね!私はすでにそれを解決しましたが、 –

+0

大丈夫です!それはあなたが最初に投稿した質問に答える場合は、とにかく答えを受け入れる必要があります... –

0

は私が最終的に裁判&エラーを通じて得た変種であるとして、あなたが提供する特定の例では、最適のJavaに変換されます。 3チャンネルの行列を繰り返し、非常に単純なフィルタを適用する(私はSamuelの例がすでにグレースケール値の集計をうまくカバーしていると信じています)。

static IplImage setSaturate_sv(IplImage imgIn) { 
    IplImage imgOut = cvCloneImage(imgIn); 
    ByteBuffer pointer = imgOut.getByteBuffer(); 

    int height = imgIn.height(); 
    int width = imgIn.width(); 
    int widthStep = imgIn.widthStep(); 
    int nChannels = imgIn.nChannels(); 
    int rowIndex; 

    for (int row = 0; row < height; row++) { 
     rowIndex = row * widthStep; 
     for (int col = 0; col < width; col++) { 
      pointer.put((rowIndex + (col * nChannels) + 1), (byte)255); 
      pointer.put((rowIndex + (col * nChannels) + 2), (byte)255); 
      pointer.put((rowIndex + (col * nChannels) + 3), /* leave alone */); 
     } 
    } 
    return imgOut; 
} 
関連する問題