我想在球拍中編寫OpenCV FFI併到達需要有效操縱數組的點。但是,我所有使用Racket FFI訪問陣列的嘗試都導致代碼非常低效。有沒有辦法使用FFI快速訪問C數組?使用球拍快速陣列訪問FFI
球拍,這種類型的操作是相當快的,即:現在
(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
,OpenCV中,有一個叫做IplImage
結構,看起來像這樣:
typedef struct _IplImage
{
int imageSize; /* sizeof(IplImage) */
...
char *imageData; /* Pointer to aligned image data.*/
}IplImage;
的結構是在球拍中定義如下:
(define-cstruct _IplImage
([imageSize _int]
...
[imageData _pointer]))
現在我們使用cvLoadImage
功能如下:
(define img
(ptr-ref
(cvLoadImage "images/test-image.png" CV_LOAD_IMAGE_COLOR)
_IplImage))
指針imageData
可以通過訪問:(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
與原生Racket矢量的速度相比,這非常緩慢。 我也試過其他方式,如_array
,_cvector
甚至不接近使用指針的速度,除了在C中編寫一個第一類函數以獲取運行整個數組的函數外。這個C函數被編譯爲一個庫,並使用FFI綁定到Racket。然後,可以將球拍程序傳遞給它並應用於數組的所有元素。速度與指針相同,但仍然不足以繼續將OpenCV庫移植到Racket。
有沒有更好的方法來做到這一點?
:)似乎在郵件列表上張貼對其他人也有幫助... –