Подушка нового изображения возвращает NULL на второй итерации с использованием Python C API - PullRequest
0 голосов
/ 04 октября 2019

Я использую скрипт Python в проекте C ++. Этот скрипт использует изображения подушек и обрабатывает их. Чтобы использовать его, я сделал небольшую инкапсуляцию API Python C. При использовании функции PIL.Image.new первый раз хорош, но во второй я получаю указатель NULL.

Короче говоря, я получаю изображения для динамической обработки в формате opencv. Я создаю свои изображения с помощью pillow.Image.new (см. ref ) и устанавливаю содержимое с помощью pillow.Image.putpixel (см. ref ). При первом вызове работает нормально, изображение корректно обрабатывается скриптом python. Как ни странно, при втором звонке вылетает. Это обычное поведение или я делаю что-то глупое здесь?

Я на Windows 7, использую Python 3.7, PILLOW на версии 5.4.1, и у меня есть все необходимые .dll либо для openCV или дляпитон. Поскольку я использую Visual Studio, я использовал отладчик для проверки всех переменных. Модуль взимается также за новый метод. Ширина и высота моего изображения хорошая, а формат правильный. И в первый И во второй (и более) раз.

Без использования инкапсуляции и перехода к точке код выглядел бы так:

cv::VideoCapture cap("PathForMyVideo");
PyObject *PIL, *Image, *ImageNew, *PILImage, *putpixel; // Pillow variables
PyObject *Arg; // Tool for arguments
cv::Mat frame;

/* PILLOW module / class / method Import */
PIL = PyImport_Import(PyUnicode_FromString("PIL"));
Image = PyObject_GetAttrString(PIL, "Image");
ImageNew= PyObject_GetAttrString(Image, "new");

// Here I load the everything from the python script that process the images

cap >> frame; // Get the frame from the video - In BGR format

while (!frame.empty())
{
    Arg = Py_BuildValue("(s(ii))", "RGB", frame.cols, frame.rows); // 1920 x 1080
    PILImage = PyEval_CallObject(ImageNew, Arg); // Here is where I receive a NULL on the second iteration
    putpixel = PyObject_GetAttrString(PILImage, "putpixel");
    Py_DECREF(Arg);

    int i = 0, x = 0, y;

    while (x < p_Rows) {
        y = 0;
        while (y < p_Cols) {
            Arg = Py_BuildValue("((ii)(iii))", y, x, (int)frame.data[i + 2], (int)frame.data[i + 1], (int)frame.data[i]); // Opencv is BGR so we have to reorder the bytes
            m_pImageSetPixel->Execute(Arg);
            Py_DECREF(Arg);
            y++;
            i += p_PixelSize;
        }
        x++;
    }
    // 1. Calls the script function
    // 2. Displays the process image using the openCV frame

    // Clean and free the pointer no longer needed
    Py_DECREF(putpixel);
    Py_DECREF(PILImage);


    cap >> frame; // Retreive a new frame and iterate
}

// Free everything from PILLOW and close the video

Мне бы хотелось иметь возможность сохранять изображение PIL в памяти и выделять его только один раз. но полученные изображения будут меняться в размерах, поэтому я должен распределять их при каждом вызове.

Я не понимаю, что у меня нет утечки памяти, моя память при необходимости освобождается. Зачем PIL.Image.new возвращать NULL при втором вызове, если при вызове у меня совпадают значения?

...