├── .gitignore ├── .gitmodules ├── .readme ├── example_003.jpg └── example_004.jpg ├── data └── 33823288584_1d21cf0a26_k.jpg ├── src ├── example_001.cpp ├── example_002.cpp ├── example_003.cpp ├── example_004.py └── example_004.cpp ├── CMakeLists.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /devel/ 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "pybind11"] 2 | path = pybind11 3 | url = https://github.com/pybind/pybind11.git 4 | -------------------------------------------------------------------------------- /.readme/example_003.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wkentaro/call-python-from-cpp/HEAD/.readme/example_003.jpg -------------------------------------------------------------------------------- /.readme/example_004.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wkentaro/call-python-from-cpp/HEAD/.readme/example_004.jpg -------------------------------------------------------------------------------- /data/33823288584_1d21cf0a26_k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wkentaro/call-python-from-cpp/HEAD/data/33823288584_1d21cf0a26_k.jpg -------------------------------------------------------------------------------- /src/example_001.cpp: -------------------------------------------------------------------------------- 1 | #include // everything needed for embedding 2 | namespace py = pybind11; 3 | 4 | int main() { 5 | py::scoped_interpreter guard{}; // start the interpreter and keep it alive 6 | 7 | py::print("Hello, World!"); // use the Python API 8 | } 9 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8 FATAL_ERROR) 2 | project(python_from_cpp) 3 | 4 | find_package(OpenCV REQUIRED) 5 | 6 | add_subdirectory(pybind11) 7 | 8 | add_executable(example_001 src/example_001.cpp) 9 | target_link_libraries(example_001 PRIVATE pybind11::embed) 10 | add_executable(example_002 src/example_002.cpp) 11 | target_link_libraries(example_002 PRIVATE pybind11::embed) 12 | add_executable(example_003 src/example_003.cpp) 13 | target_link_libraries(example_003 PRIVATE pybind11::embed) 14 | add_executable(example_004 src/example_004.cpp) 15 | target_link_libraries(example_004 PRIVATE pybind11::embed ${OpenCV_LIBS}) 16 | -------------------------------------------------------------------------------- /src/example_002.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include // everything needed for embedding 3 | namespace py = pybind11; 4 | 5 | int main(int argc, char** argv) 6 | { 7 | py::scoped_interpreter guard{}; // start the interpreter and keep it alive 8 | 9 | py::object sys = py::module::import("sys"); 10 | std::string sys_version = sys.attr("version").cast(); 11 | std::cout << "sys version: " << sys_version << std::endl; 12 | 13 | py::object scipy = py::module::import("scipy"); 14 | std::string scipy_version = scipy.attr("__version__").cast(); 15 | std::cout << "scipy version: " << scipy_version << std::endl; 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/example_003.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | namespace py = pybind11; 5 | 6 | int main() { 7 | py::scoped_interpreter guard{}; 8 | 9 | py::object scipy_misc = py::module::import("scipy.misc"); 10 | py::object plt = py::module::import("matplotlib.pyplot"); 11 | 12 | py::array_t img = scipy_misc.attr("face")() 13 | .cast >(); 14 | std::cout << "shape: " << img.shape()[0] << " " << img.shape()[1] << " " << img.shape()[2] << std::endl; 15 | std::cout << "ndim: " << img.ndim() << std::endl; 16 | 17 | py::object img_py = py::cast(img); 18 | std::cout << "==> Saved to: image.jpg" << std::endl; 19 | plt.attr("imsave")("image.jpg", img_py); 20 | } 21 | -------------------------------------------------------------------------------- /src/example_004.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import chainer 4 | from chainercv.datasets import coco_instance_segmentation_label_names 5 | from chainercv.links import MaskRCNNFPNResNet50 6 | import imgviz 7 | import numpy as np 8 | 9 | 10 | def main(): 11 | gpu = 0 12 | image_file = '../data/33823288584_1d21cf0a26_k.jpg' 13 | 14 | chainer.config.cv_resize_backend = 'cv2' 15 | 16 | label_names = coco_instance_segmentation_label_names 17 | model = MaskRCNNFPNResNet50( 18 | n_fg_class=len(label_names), 19 | pretrained_model='coco', 20 | ) 21 | 22 | chainer.cuda.get_device_from_id(gpu).use() 23 | model.to_gpu() 24 | 25 | img = imgviz.io.imread(image_file) 26 | img_input = img.transpose(2, 0, 1).astype(np.float32) 27 | 28 | masks, labels, scores = model.predict([img_input]) 29 | masks = masks[0] 30 | labels = labels[0] 31 | scores = scores[0] 32 | class_ids = labels + 1 33 | captions = [ 34 | '{:s}: {:.2%}'.format(label_names[c - 1], s) 35 | for c, s in zip(class_ids, scores) 36 | ] 37 | viz = imgviz.instances2rgb( 38 | image=img, 39 | labels=class_ids, 40 | masks=masks, 41 | captions=captions, 42 | font_size=15, 43 | ) 44 | 45 | imgviz.io.pyglet_imshow(viz) 46 | imgviz.io.pyglet_run() 47 | 48 | 49 | if __name__ == '__main__': 50 | main() 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # call-python-from-cpp 2 | 3 | Example Code of Calling Python from C++, 4 | following the instruction 5 | Embedding the Interpreter. 6 | 7 | ## Installation 8 | 9 | ```bash 10 | # for example_001 - example_003 11 | sudo python3 -m pip install numpy 12 | sudo python3 -m pip install scipy 13 | 14 | # for example_004 15 | sudo python3 -m pip install opencv-python 16 | sudo python3 -m pip install chainer 17 | sudo python3 -m pip install chainercv 18 | sudo python3 -m pip install imgviz 19 | sudo python3 -m pip install pyglet 20 | sudo python3 -m pip install cupy-cuda101 # CUDA10.1, cupy-cuda92 for 9.2 21 | ``` 22 | 23 | ```bash 24 | mkdir build 25 | cd build 26 | 27 | cmake .. 28 | make 29 | ``` 30 | 31 | 32 | ## Examples 33 | 34 | ### Hello World! ([src/example_001.cpp](src/example_001.cpp)) 35 | 36 | ```bash 37 | $ cd build 38 | $ ./example_001 39 | Hello, World! 40 | ``` 41 | 42 | ### Import SciPy ([src/example_002.cpp](src/example_002.cpp)) 43 | 44 | ```bash 45 | $ cd build 46 | $ ./example_002 47 | sys version: 3.5.2 (default, Nov 12 2018, 13:43:14) 48 | [GCC 5.4.0 20160609] 49 | scipy version: 1.3.0 50 | ``` 51 | 52 | ### Communicate Numpy Array ([src/example_003.cpp](src/example_003.cpp)) 53 | 54 | ```bash 55 | $ cd build 56 | $ ./example_003 57 | shape: 768 1024 3 58 | ndim: 3 59 | ==> Saved to: image.jpg 60 | ``` 61 | 62 |
`image.jpg` 63 | 64 | ### Run Mask R-CNN ([src/example_004.cpp](src/example_004.cpp)) 65 | 66 | ```bash 67 | $ cd build 68 | $ ./example_004 69 | ndim: 3 70 | shape: (600, 956, 3, ) 71 | ``` 72 | 73 |
`cv::imshow(...)` 74 | -------------------------------------------------------------------------------- /src/example_004.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace py = pybind11; 6 | using namespace py::literals; 7 | 8 | int main() { 9 | py::scoped_interpreter guard{}; 10 | 11 | auto locals = py::dict(); 12 | py::exec(R"( 13 | import chainer 14 | from chainercv.datasets import coco_instance_segmentation_label_names 15 | from chainercv.links import MaskRCNNFPNResNet50 16 | from chainercv import utils 17 | import imgviz 18 | import numpy as np 19 | 20 | gpu = 0 21 | image_file = '../data/33823288584_1d21cf0a26_k.jpg' 22 | 23 | chainer.config.cv_resize_backend = 'cv2' 24 | 25 | label_names = coco_instance_segmentation_label_names 26 | model = MaskRCNNFPNResNet50( 27 | n_fg_class=len(label_names), 28 | pretrained_model='coco', 29 | ) 30 | 31 | chainer.cuda.get_device_from_id(gpu).use() 32 | model.to_gpu() 33 | 34 | img = imgviz.io.imread(image_file) 35 | img_input = img.transpose(2, 0, 1).astype(np.float32) 36 | 37 | masks, labels, scores = model.predict([img_input]) 38 | masks = masks[0] 39 | labels = labels[0] 40 | scores = scores[0] 41 | class_ids = labels + 1 42 | captions = [] 43 | for c, s in zip(class_ids, scores): 44 | captions.append('{:s}: {:.2%}'.format(label_names[c - 1], s)) 45 | viz = imgviz.instances2rgb( 46 | image=img, 47 | labels=class_ids, 48 | masks=masks, 49 | captions=captions, 50 | font_size=15, 51 | ) 52 | )", py::globals(), locals); 53 | 54 | std::string image_file = locals["image_file"].cast(); 55 | py::array_t viz = locals["viz"].cast >(); 56 | std::cout << "ndim: " << viz.ndim() << std::endl; 57 | std::cout << "shape: ("; 58 | for (size_t i = 0; i < viz.ndim(); i++) { 59 | std::cout << viz.shape()[i] << ", "; 60 | } 61 | std::cout << ")" << std::endl; 62 | 63 | // pybind11::array_t -> cv::Mat 64 | // TODO(unknown): more efficient implementation 65 | unsigned int rows = viz.shape(0); 66 | unsigned int cols = viz.shape(1); 67 | cv::Mat viz_mat = cv::Mat::zeros(/*rows=*/rows, /*cols=*/cols, CV_8UC3); 68 | for (size_t i = 0; i < rows; i++) { 69 | for (size_t j = 0; j < cols; j++) { 70 | // RGB -> BGR 71 | viz_mat.at(/*row=*/i, /*col=*/j) = cv::Vec3b( 72 | *viz.data(i, j, 2), *viz.data(i, j, 1), *viz.data(i, j, 0) 73 | ); 74 | } 75 | } 76 | 77 | cv::imshow(image_file, viz_mat); 78 | cv::waitKey(0); 79 | } 80 | --------------------------------------------------------------------------------