#include "logger.h" #include "cnnpredict_interface.h" #include "common.h" #include "py_cnnpredict.h" template vector ndarray_to_vector(const py::array &nd) { py::dtype datatype = nd.dtype(); size_t nd_dim = nd.ndim(); const auto *shape = nd.shape(); size_t data_num = nd.size(); // py::buffer_info buf = nd.request(); const T *nd_data = reinterpret_cast(nd.data(0)); vector vec(data_num, 0); std::copy(nd_data, nd_data + data_num, vec.begin()); return vec; } template vector list_to_vector(py::list &list) { vector vec; for (size_t i = 0; i < py::len(list); i++) { T l = py::cast(list[i]); vec.push_back(l); } return vec; } template vector> ndlist_to_vectors(py::list &ndlist) { vector> vecs; for (unsigned int i = 0; i < py::len(ndlist); i++) { py::array nd = py::array(ndlist[i]); vector vec = ndarray_to_vector(nd); vecs.push_back(vec); } return vecs; } template py::array vector_to_ndarray(const vector &vec) { const std::vector shape = {vec.size()}; auto format = py::format_descriptor::format(); py::dtype dt(format); py::array nd(dt, shape, (const char *)vec.data()); return nd; } template py::list vectors_to_list(const vector> &vecs) { py::list ndlist; for (int i = 0; i < vecs.size(); i++) { py::array nd = vector_to_ndarray(vecs[i]); ndlist.append(nd); } return ndlist; } PyCNNPredict::~PyCNNPredict() { if (_predictor != NULL) { delete _predictor; _predictor = NULL; } } bool PyCNNPredict::init(string conf_file, string prefix) { LOG(INFO) << "PyCNNPredict::init()"; _predictor = create_cnnpredict(conf_file, prefix); if (_predictor == NULL) { LOG(FATAL) << "fail to call create_cnnpredict"; return false; } return true; } py::list PyCNNPredict::postprocess(const vector> &vdatas, const vector> &vshapes) { LOG(INFO) << "PyCNNPredict::postprocess()"; py::list result; if (vdatas.size() != vshapes.size()) { LOG(FATAL) << "datas and shapes size not equal"; return result; } result.append(vectors_to_list(vdatas)); result.append(vectors_to_list(vshapes)); return result; } py::list PyCNNPredict::predict(py::list input_datas, py::list input_shapes, py::list layer_names) { LOG(INFO) << "PyCNNPredict::predict()"; vector> inputdatas; vector> inputshapes; vector layernames; vector> outputdatas; vector> outputshapes; py::list result; if (py::len(input_datas) != py::len(input_shapes)) { LOG(FATAL) << "datas and shapes size not equal"; return result; } inputdatas = ndlist_to_vectors(input_datas); inputshapes = ndlist_to_vectors(input_shapes); layernames = list_to_vector(layer_names); bool ret = _predictor->predict( inputdatas, inputshapes, layernames, outputdatas, outputshapes); if (!ret) { LOG(FATAL) << "fail to predict"; return result; } return postprocess(outputdatas, outputshapes); } PYBIND11_MODULE(PyCNNPredict, m) { m.doc() = "pycnnpredict"; py::class_(m, "PyCNNPredict") .def(py::init()) .def("init", &PyCNNPredict::init) .def("predict", &PyCNNPredict::predict); }