Передача прокси-объекта SWIG в качестве входных данных для PIL.Image.frombuffer

Я использую макрос SWIG array_class, определенный в carrays.i, для создания беззнакового буфера char, который можно отправить на сторону C++ моего проекта, которая обрабатывает снимки. Это работает нормально — буфер заполняется данными ширины после срабатывания камеры, и я могу разыменовать буфер, используя [] из python, чтобы увидеть, что он содержит. Теперь я хочу создать изображение PIL из этого буфера, используя Image.frombuffer:

Image.frombuffer(mode, size, data) => image

(Новое в PIL 1.1.4). Создает память изображения из пиксельных данных в строке или буферном объекте, используя стандартный "необработанный" декодер.

но я получаю сообщение об ошибке, говорящее мне, что объект SWIG, который я предоставляю, не является буфером python:

Файл "/usr/lib/python2.7/dist-packages/PIL/Image.py", строка 1853, в frombuffer
core.map_buffer(data, size, decoder_name, None, 0, args)
TypeError : ожидаемая строка или буфер

Как я могу сделать этот прокси объекта SWIG совместимым с типом буфера, который ожидает Image.frombuffer?


person Paul    schedule 11.01.2012    source источник
comment
Я не уверен, что он должен работать с буфером (вероятно, должен). Я просто хотел отметить, что мне нравится соединять все данные изображений через массивы NumPy. IMO проще манипулировать объектами NumPy Python непосредственно из C++, чем пытаться заставить SWIG генерировать правильный код. У меня есть пример кода в Интернете. Вы можете позволить SWIG обернуть метод, который возвращает PyObject*, и вернуть новый объект NumPy, созданный с помощью PyArray_SimpleNew().   -  person maxy    schedule 12.01.2012
comment
Вы где-то знаете длину каррейного типа?   -  person Flexo    schedule 13.01.2012


Ответы (1)


Если вы можете справиться с принудительной подписью вашего буфера SWIG, вы можете напрямую создать PIL ImagingMemoryInstance. В libImaging/Imaging.h вы найдете это:

struct ImagingMemoryInstance {

    /* Format */
    char mode[4+1]; /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK") */
    int type;       /* Data type (IMAGING_TYPE_*) */
    int depth;      /* Depth (ignored in this version) */
    int bands;      /* Number of bands (1, 2, 3, or 4) */
    int xsize;      /* Image dimension. */
    int ysize;

    /* Colour palette (for "P" images only) */
    ImagingPalette palette;

    /* Data pointers */
    UINT8 **image8; /* Set for 8-bit images (pixelsize=1). */
    INT32 **image32;    /* Set for 32-bit images (pixelsize=4). */

    /* Internals */
    char **image;   /* Actual raster data. */
    char *block;    /* Set if data is allocated in a single block. */

    int pixelsize;  /* Size of a pixel, in bytes (1, 2 or 4) */
    int linesize;   /* Size of a line, in bytes (xsize * pixelsize) */

    /* Virtual methods */
    void (*destroy)(Imaging im);
};

... ImagingMemoryInstance* имеет typedef'd к Imaging, что является базовой структурой, которую вы повсеместно найдете в исходном коде расширения PIL C. Не верьте мне на слово, посмотрите -- что касается исходного кода API, кодовая база PIL особенно разборчива и довольно связна.

Как указывает @maxy, вы также можете создать структуру массива NumPy так же легко (если не проще), но хотя API-интерфейс NumPy C так же стабилен, как и из личного сборника игр Гвидо, я лично считаю, что одна зависимость от источника библиотеки достаточно, в этих сценариях.

person fish2000    schedule 02.03.2012
comment
Кроме того: это не прокси SWIG, но: проверьте буфер, который этот парень настраивает для перехода туда и обратно с PIL: bitbucket.org/ynil/pyccv/src/d201d144e8e9/src/pyccv/__init__.py ... класс Python RGBImage на самом деле является структурой C, чья Макет байта аналогичен dtype, эквивалентному массиву NumPy. Я не знаю ctypes как босс, но если бы у меня была твоя проблема, я бы поиграл с чем-то вроде этого. - person fish2000; 15.03.2012