Как создать изменяемый массив Racket из указателя C для изменения образа OpenCV? - PullRequest
3 голосов
/ 14 января 2020

Я играю с этими привязками OpenCV для Racket , и я хотел бы иметь возможность доступа к значениям пикселей в виде массива, в основном, чтобы я мог использовать индексирование столбцов строк. В примерах только показано, как вызывать высокоуровневые функции OpenCV, а затем доступ к необработанным данным отображается только при низкоуровневом доступе к bytestring .

. Все это прекрасно работает, я был довольно впечатлен. Думаю, что для некоторых приложений мы должны быть в состоянии выполнять попиксельную обработку, в идеале используя любой объект многомерного массива в Racket, который выглядит как math:array. Вопрос в том, как создать этот изменяемый массив из объекта IplImage.

Мне удалось запустить пример bytestring, который уже не идеален, поскольку он не поддерживает другие типы, такие как float. Следующий фрагмент кода работает, создавая cvector из указателя на данные изображения:

(define xx (make-cvector* (IplImage-imageData frame) ffi:_uint8 307200))
(cvector-set! xx ii 255)
(set! ii (ii . + . 1) )

Это рисует пиксель, движущийся в каждом кадре внутри al oop ... Это работает. Теперь я хотел бы создать массив из этого cvector. Я придумал следующий код:

(define (image->array image)
  (let ([data
         (make-cvector* (IplImage-imageData image)
                        ffi:_uint8
                        (IplImage-imageSize image))]
        [shape (vector (IplImage-height image) (IplImage-width image))])
    (array->mutable-array (list->array
                           shape
                           (cvector->list data)))))

Это, очевидно, работает для чтения, но не для обратной записи. Как мне сделать его на самом деле изменчивым? И есть ли здесь проблемы с производительностью? Возможно ли cvector->list скопировать все данные в новый список Racket? Как создать векторный объект Racket, который может использоваться math:array?

1 Ответ

1 голос
/ 15 января 2020

Ваш код действительно возвращает изменяемый массив. Просто он работает только для изображений в оттенках серого, поскольку list->array ожидает список длины (* ширина высоты), а cvector->list возвращает список длины (* ширина канала высоты). Пройдя весь путь: cpointer >> cvector >> list >> immutable-array >> mutable-array просто иметь индексирование строки-столбца кажется слишком сложным, так как вы можете определить функцию для «моделирования» желаемого стиля доступа .

Что касается проблем производительности, см. Этот вопрос StackOverflow [1] (создатель racket-opencv), который объясняет причины, стоящие за байтами и функцией IplImage-data. Вы уже упоминали, что строки байтов не идеальны для вас, но, тем не менее, даже если вам нужно go к векторам (или математике / массиву), попробуйте также путь: cpointer >> bytestring >> list >> vector (быстрее в моем машина).

[1] Быстрый доступ к массиву с использованием Racket FFI

...