2012-05-08 12 views
3

私はOpenCV FFIをRacketに書き込もうとしており、アレイを効率的に操作する必要があるところに到着しました。しかし、Racket FFIを使用して配列にアクセスしようとする私の試みはすべて、非常に非効率なコードとなっていました。 FFIを使用してC配列に高速アクセスする方法はありますか?Racket FFIを使用した高速アレイアクセス

typedef struct _IplImage 
{ 
    int imageSize;    /* sizeof(IplImage) */ 
    ... 
    char *imageData;  /* Pointer to aligned image data.*/ 
}IplImage; 

構造体です:OpenCVの中で、このようになりますIplImageと呼ばれる構造体があり、

(define a-vector (make-vector (* 640 480 3))) 
(time (let loop ([i (- (* 640 480 3) 1)]) 
    (when (>= i 0) 
     ;; invert each pixel channel-wise 
     (vector-set! a-vector i (- 255 (vector-ref a-vector i))) 
     (loop (- i 1))))) 
-> cpu time: 14 real time: 14 gc time: 0 

今:ラケットで

は、このタイプの操作はすなわち、適度に高速であります

(define-cstruct _IplImage 
    ([imageSize _int] 
    ... 
    [imageData _pointer])) 

ここで、次のように画像をロードします。

(define img 
    (ptr-ref 
    (cvLoadImage "images/test-image.png" CV_LOAD_IMAGE_COLOR) 
    _IplImage)) 

ポインタimageDataによってアクセスすることができます:cvLoadImage関数は次のように今(define data (IplImage-imageData img)))

は、我々はdataを操作したい、と私が思い付くことができる最も効率的な方法は、使用するポインタであった。

(time (let loop ([i (- (* width height channels) 1)]) ;; same 640 480 3 
    (when (>= i 0) 
     ;; invert each pixel channel-wise 
     (ptr-set! data _ubyte i (- 255 (ptr-ref data _ubyte i))) 
     (loop (- i 1))))) 
-> cpu time: 114 real time: 113 gc time: 0 

これはネイティブラケットベクトルの速度に比べて非常に遅いです。 また、_array,_cvectorのように、ポインタを使う速度にも至らず、C言語で関数全体を実行するためのファーストクラスの関数を書く以外は試しました。このC関数はライブラリにコンパイルされ、FFIを使用してRacketでバインドされます。次に、Racketプロシージャを渡して、配列のすべての要素に適用することができます。速度はポインタと同じでしたが、OpenCVライブラリをRacketに移植するのにはまだ十分ではありません。

これを行うより良い方法はありますか?

答えて

4

私はEliによって提案されたアプローチを試してみました!アイデアは、バイトテストを使用することです。この場合には、配列のサイズは(make-sized-byte-string cptr length)を使用することができ、知られているので:

(define data (make-sized-byte-string (IplImage-imageData img) 
            (* width height channels))) 

これはラケットのネイティブのベクトルに近い実行時間になり:

(time (let loop ([i (- (* 640 480 3) 1)]) 
    (when (>= i 0) 
     ;; invert each pixel channel-wise 
     (bytes-set! data i (- 255 (bytes-ref data i))) 
     (loop (- i 1))))) 
-> cpu time: 18 real time: 18 gc time: 0 

は、イーライ、ありがとうございました。

+0

:)メーリングリストへの投稿が他の人にも役立つようです... –

2

bytestring(_bytes経由)を使用して全体を設定する方が良いでしょうが、それは非常におおまかな推測です。この質問をメーリングリストで尋ねる方がはるかに良いでしょう...

+0

私はラケット 'users'メーリングリストで質問を再投稿しました。 –

+0

うーん、メーリングリストで誰も答えてくれないようです。この場合、バイトテストをどのように使用できますか? –

関連する問題