私は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に移植するのにはまだ十分ではありません。
これを行うより良い方法はありますか?
:)メーリングリストへの投稿が他の人にも役立つようです... –