我试图以简单的方式从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上的两个建议转换器(1,2),但不幸的是它们与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))
,但我不知道它是否按预期工作。