只需通过缓冲区和字符串将图像从python发送到C ++

时间:2016-11-03 16:06:26

标签: python c++ opencv

我试图以简单的方式从Python程序发送一个返回ndarray到C ++(OpenCV Mat)的图像:将图像保存到缓冲区然后将缓冲区内容作为字符串传递给C ++并在那里使用cv::imdecode

cv::imshow在c ++中抛出错误:

OpenCV Error: Assertion failed (size.width>0 && size.height>0) in imshow, 
file /home/hcl/opencv-3.1.0/modules/highgui/src/window.cpp, line 281
terminate called after throwing an instance of 'cv::Exception'
  what():  /home/hcl/opencv-3.1.0/modules/highgui/src/window.cpp:281: 
error: (-215) size.width>0 && size.height>0 in function imshow

Aborted (core dumped)

编辑:它有效。

在此之前,我已经阅读了许多方法,在StackOverflow上将ndarray从Python发送到C ++,并且没有管理它们。我还检查了Github上的两个建议转换器(12),但不幸的是它们与OpenCV 3不兼容。由于无法解决问题,我希望以这种最简单的方式使其工作避免将来可能的移植问题。

返回图片的Python脚本imgread.py):

import scipy.misc
import click as _click

import base64
from io import BytesIO

def get_my_image(image_name):

    # using click package to make sure that path is interpreted correctly
    _click.command()
    _click.argument('image_name',type=_click.Path(exists=True,
                                dir_okay=True, readable=True))

    # just reading some image (ndarray format is essential)
    image = scipy.misc.imread(image_name)

    # processing data ....

    # sending it back-----------------------------------

    # I've heard that scipy version started to normalize all images, 
    # but at the moment I just want to start it working
    img_to_send = scipy.misc.toimage(image) 

    # https://stackoverflow.com/questions/31826335/
    # how-to-convert-pil-image-image-object-to-base64-string
    # preparing buffer and writing image to it
    mybuffer = BytesIO()
    img_to_send.save(mybuffer, format="JPEG")

    # converting buffer contents to string
    img_str = base64.b64encode(mybuffer.getvalue())  

    return(img_str) 

原始工作* .cpp示例为here,我只更改了与处理数据相对应的部分。

主要C ++程序: (EDITED.base64转换代码取自here

// call_function.c - A sample of calling 
// python functions from C code

// original code from

// https://stackoverflow.com/questions/215752/
// python-embedded-in-cpp-how-to-get-data-back-to-cpp

#include <Python.h>

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"

#include <iostream>

#include <string>
#include "base64.cpp"

using namespace cv;
using namespace std;

int
main(int argc, char *argv[])
{
    PyObject *pName, *pModule, *pFunc;
    PyObject *pArgs, *pArg, *pResult;
    int i;

    Py_Initialize();
    pName = PyString_FromString("imgread");
    // (no .py, error "ImportError: No module named py" otherwise)
    /* Error checking of pName left out as exercise */

    pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    if (pModule != NULL) {
        pFunc = PyObject_GetAttrString(pModule, "get_my_image");
        /* pFunc is a new reference */

        if (pFunc) {
            pArgs = PyTuple_New(1);
            pArg = PyString_FromString("1.jpg");
            /* pArg reference stolen here: */
            PyTuple_SetItem(pArgs, 0, pArg);
            pResult = PyObject_CallObject(pFunc, pArgs);
            Py_DECREF(pArgs);
            if (pResult != NULL) {

                //------------------------------- my part

            // see https://stackoverflow.com/questions/14727267/
            // opencv-read-jpeg-image-from-buffer


            char* str = PyString_AsString(pResult);

            // converting back from base64
            const std::string base64_chars = string(str);

            string s = base64_decode(base64_chars);                

            char* str3 = (char*)s.c_str();

            //taking NULLs into account and using s.size()
            size_t len = s.size();
            uchar* str2 = reinterpret_cast<unsigned char*>(str3);

                //attempting to display the image
                Mat rawData(1, len*sizeof(uchar), CV_8UC1, str2);
                Mat decodedImage  =  imdecode(rawData,CV_LOAD_IMAGE_COLOR);
                imshow( "Display window", decodedImage ); 

                //------------------------------- 

                Py_DECREF(pResult);

            }
            else {
                Py_DECREF(pFunc);
                Py_DECREF(pModule);
                PyErr_Print();
                fprintf(stderr,"Call failed\n");
                return 1;
            }
        }
        else {
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function");
        }
        Py_XDECREF(pFunc);
        Py_DECREF(pModule);
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load module");
        return 1;
    }
    Py_Finalize();

    waitKey(0);
    return 0;
}

编辑:要摆脱scipy.misc.toimage执行的规范化,我尝试使用img_to_send = scipy.misc.toimage(image,high=np.max(image), low=np.min(image)),但我不知道它是否按预期工作。

0 个答案:

没有答案