├── little_demo ├── add ├── evaluate.py ├── makefile └── add.cpp ├── test_pic ├── cat.jpeg ├── tiger.jpeg └── puzzle.jpeg ├── makefile ├── CMakeLists.txt ├── prediction.cpp ├── vgg_model.py └── readme.md /little_demo/add: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BIGBALLON/CPP-Call-Tensorflow/HEAD/little_demo/add -------------------------------------------------------------------------------- /test_pic/cat.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BIGBALLON/CPP-Call-Tensorflow/HEAD/test_pic/cat.jpeg -------------------------------------------------------------------------------- /test_pic/tiger.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BIGBALLON/CPP-Call-Tensorflow/HEAD/test_pic/tiger.jpeg -------------------------------------------------------------------------------- /test_pic/puzzle.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BIGBALLON/CPP-Call-Tensorflow/HEAD/test_pic/puzzle.jpeg -------------------------------------------------------------------------------- /little_demo/evaluate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | def addition(a, b): 4 | return a + b 5 | 6 | 7 | -------------------------------------------------------------------------------- /little_demo/makefile: -------------------------------------------------------------------------------- 1 | all: 2 | g++ -std=c++11 -Wall -O3 add.cpp -lpython3.5m -L/usr/include/python3.5m/ -I/usr/include/python3.5m/ -o add 3 | clean: 4 | rm add 5 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | all: 2 | g++ -std=c++11 -Wall -O3 prediction.cpp -lpython3.5m -L/usr/include/python3.5m/ -I/usr/include/python3.5m/ -o pred_test 3 | clean: 4 | rm pred_test 5 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT(c_call_python) 4 | 5 | SET(EXECUTABLE classifier) 6 | SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++11 -Wall -O3") 7 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}) 8 | 9 | FILE(GLOB SRC_FILES prediction.cpp) 10 | 11 | ADD_EXECUTABLE(${EXECUTABLE} ${SRC_FILES}) 12 | 13 | FIND_PACKAGE(PythonInterp 3.5 REQUIRED) 14 | FIND_PACKAGE(PythonLibs 3.5 REQUIRED) 15 | MESSAGE(STATUS "PYTHON_LIBRARIES = ${PYTHON_LIBRARIES}") 16 | MESSAGE(STATUS "PYTHON_INCLUDE_DIRS = ${PYTHON_INCLUDE_DIRS}") 17 | 18 | SET(PROJECT_LIBRARIES ${PYTHON_LIBRARIES} ) 19 | SET(PROJECT_INCLUDES ${PYTHON_INCLUDE_DIRS} ) 20 | 21 | MESSAGE(Project_include_path: ${PROJECT_INCLUDES}) 22 | MESSAGE(Project_libraries_path: ${PROJECT_LIBRARIES}) 23 | INCLUDE_DIRECTORIES(${PROJECT_INCLUDES}) 24 | TARGET_LINK_LIBRARIES(${EXECUTABLE} ${PROJECT_LIBRARIES}) 25 | 26 | -------------------------------------------------------------------------------- /prediction.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | int main(int argc, char *argv[]){ 7 | 8 | Py_Initialize(); 9 | if( !Py_IsInitialized() ){ 10 | printf("Initialize failed\n"); 11 | return -1; 12 | } 13 | PyRun_SimpleString("import sys"); 14 | PyRun_SimpleString("sys.path.append('./')"); 15 | 16 | PyObject *pName,*pModule,*pDict,*pFunc; 17 | 18 | // PyString_FromString for python2.x 19 | // PyUnicode_DecodeFSDefault for python3.x 20 | pName = PyUnicode_DecodeFSDefault("vgg_model"); 21 | 22 | pModule = PyImport_Import(pName); 23 | if ( !pModule ){ 24 | printf("Can't find Module\n"); 25 | PyErr_Print(); 26 | return -1; 27 | } 28 | pDict = PyModule_GetDict(pModule); 29 | if ( !pDict ){ 30 | return -1; 31 | } 32 | pFunc = PyDict_GetItemString(pDict, "predict"); 33 | if ( !pFunc || !PyCallable_Check(pFunc) ){ 34 | printf("can't find function [predict]\n"); 35 | return -1; 36 | } 37 | 38 | 39 | printf(" ===========> START CALL PYTHON SCRIPT <===========\n"); 40 | 41 | printf(" ===========> 1st CALL <===========\n"); 42 | PyObject_CallObject(pFunc,NULL); 43 | printf(" ===========> 2nd CALL <===========\n"); 44 | PyObject_CallObject(pFunc,NULL); 45 | printf(" ===========> 3rd CALL <===========\n"); 46 | PyObject_CallObject(pFunc,NULL); 47 | printf(" ===========> 4th CALL <===========\n"); 48 | PyObject_CallObject(pFunc,NULL); 49 | 50 | printf(" ===========> CALLING FINISHED <===========\n"); 51 | 52 | Py_DECREF(pName); 53 | Py_DECREF(pModule); 54 | 55 | // close Python 56 | Py_Finalize(); 57 | return 0; 58 | } -------------------------------------------------------------------------------- /vgg_model.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | sys.argv = ['pdm'] 4 | import keras 5 | from keras.applications.vgg19 import VGG19 6 | from keras.applications.vgg19 import preprocess_input, decode_predictions 7 | from PIL import Image 8 | import numpy as np 9 | import os.path 10 | 11 | # Using ImageNet pre_trained weights to predict image's class(1000 class) 12 | # ImageNet -- http://www.image-net.org/ 13 | 14 | # Load keras ImageNet pre_trained model 15 | # If weight not exist, it will download & save to ~/.keras/models/ 16 | 17 | model = VGG19(weights='imagenet') 18 | 19 | def predict(): 20 | img_path = input(' Please input picture file to predict: ') 21 | if not os.path.exists(img_path): 22 | print(" file not exist!") 23 | return 24 | try: 25 | img = Image.open(img_path) 26 | ori_w,ori_h = img.size 27 | new_w = 224.0; 28 | new_h = 224.0; 29 | if ori_w > ori_h: 30 | bs = 224.0 / ori_h; 31 | new_w = ori_w * bs 32 | weight = int(new_w) 33 | height = int(new_h) 34 | img = img.resize( (weight, height), Image.BILINEAR ) 35 | region = ( weight / 2 - 112, 0, weight / 2 + 112, height) 36 | img = img.crop( region ) 37 | else: 38 | bs = 224.0 / ori_w; 39 | new_h = ori_h * bs 40 | weight = int(new_w) 41 | height = int(new_h) 42 | img = img.resize( (weight, height), Image.BILINEAR ) 43 | region = ( 0, height / 2 - 112 , weight, height / 2 + 112 ) 44 | img = img.crop( region ) 45 | x = np.array( img, dtype = 'float32' ) 46 | x[:, :, 0] = x[:, :, 0] - 123.680 47 | x[:, :, 1] = x[:, :, 1] - 116.779 48 | x[:, :, 2] = x[:, :, 2] - 103.939 49 | x = np.expand_dims(x, axis=0) 50 | results = model.predict(x) 51 | print(' Predicted: ', decode_predictions(results, top=1)[0]) 52 | except Exception as e: 53 | print(img_path) 54 | pass 55 | return 56 | 57 | if __name__ == '__main__': 58 | predict() 59 | -------------------------------------------------------------------------------- /little_demo/add.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]){ 6 | 7 | Py_Initialize(); 8 | if( !Py_IsInitialized() ){ 9 | printf("Initialize failed\n"); 10 | return -1; 11 | } 12 | PyRun_SimpleString("import sys"); 13 | PyRun_SimpleString("sys.path.append('./')"); 14 | 15 | PyObject *pName, *pModule, *pDict, *pFunc, *pArgs, *pRet; 16 | 17 | 18 | pName = PyUnicode_DecodeFSDefault("evaluate"); 19 | 20 | pModule = PyImport_Import(pName); 21 | if ( !pModule ){ 22 | return -1; 23 | } 24 | pDict = PyModule_GetDict(pModule); 25 | if ( !pDict ){ 26 | return -1; 27 | } 28 | pFunc = PyDict_GetItemString(pDict, "addition"); 29 | if ( !pFunc || !PyCallable_Check(pFunc) ){ 30 | return -1; 31 | } 32 | 33 | long arr1[5] = {1, 3, 5, 7, 9}; 34 | long arr2[5] = {2, 4, 6, 8, 10}; 35 | long total = 0; 36 | 37 | 38 | pArgs = PyTuple_New(2); // create a tuple which has two elements 39 | 40 | for( int i = 0; i < 5; ++i ){ 41 | 42 | //PyLong_AsLong for python3.x 43 | //PyInt_AsLong for python2.x 44 | 45 | PyObject* arg1 = PyLong_FromLong(arr1[i]); // set para1 46 | PyObject* arg2 = PyLong_FromLong(arr2[i]); // set para2 47 | PyTuple_SetItem(pArgs, 0, arg1); // set tuple 48 | PyTuple_SetItem(pArgs, 1, arg2); 49 | 50 | printf(" ===========> START CALL PYTHON SCRIPT %d <===========\n", i + 1); 51 | pRet = PyObject_CallObject(pFunc, pArgs); // call the function 52 | printf(" ===========> CALLING FINISHED %d <===========\n", i + 1); 53 | 54 | long result = PyLong_AsLong(pRet); // get the return value by pRet 55 | printf(" ===========> result = %ld <===========\n", result); 56 | 57 | total += result; 58 | } 59 | 60 | printf(" ===========> total = %ld <===========\n", total); 61 | 62 | Py_DECREF(pName); 63 | Py_DECREF(pModule); 64 | Py_DECREF(pArgs); 65 | Py_DECREF(pRet); 66 | Py_DECREF(pDict); 67 | 68 | // close Python 69 | Py_Finalize(); 70 | return 0; 71 | } 72 | 73 | /* 74 | bg@bg-cgi:~/Desktop/C_python/little_demo$ make all 75 | g++ -std=c++11 -Wall -O3 add.cpp -lpython3.5m -L/usr/include/python3.5m/ -I/usr/include/python3.5m/ -o add 76 | bg@bg-cgi:~/Desktop/C_python/little_demo$ ./add 77 | ===========> START CALL PYTHON SCRIPT 1 <=========== 78 | ===========> CALLING FINISHED 1 <=========== 79 | ===========> result = 3 <=========== 80 | ===========> START CALL PYTHON SCRIPT 2 <=========== 81 | ===========> CALLING FINISHED 2 <=========== 82 | ===========> result = 7 <=========== 83 | ===========> START CALL PYTHON SCRIPT 3 <=========== 84 | ===========> CALLING FINISHED 3 <=========== 85 | ===========> result = 11 <=========== 86 | ===========> START CALL PYTHON SCRIPT 4 <=========== 87 | ===========> CALLING FINISHED 4 <=========== 88 | ===========> result = 15 <=========== 89 | ===========> START CALL PYTHON SCRIPT 5 <=========== 90 | ===========> CALLING FINISHED 5 <=========== 91 | ===========> result = 19 <=========== 92 | ===========> total = 55 <=========== 93 | */ -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 2 | # Calling TensorFlow Python Program from C++ 3 | 4 | This Demo will show how to call an pre-trained imagenet model to predict picture in C++. 5 | 6 | ``` 7 | ├─ prediction.cpp % C++ file 8 | ├─ vgg_model.py % TensorFlow vgg model 9 | ├─ makefile % Compile file 10 | ├─ little_demo % An simple Demo 11 | └─ test_pic/ % Test pictures 12 | ├─ cat.jpeg 13 | ├─ puzzle.jpeg 14 | └─ tiger.jpeg 15 | ``` 16 | 17 | ## The python script 18 | 19 | Firstly, we need an python script which let us to load VGG model & use it to do predict op. 20 | 21 | You can test the script ``vgg_model.py`` by using the following cmd: 22 | 23 | 24 | ``` 25 | (deeplearning) bg@bg-cgi:~/Desktop/C_python$ python3 vgg_model.py 26 | Using TensorFlow backend. 27 | 28 | ... 29 | ... 30 | ... 31 | 32 | Please input picture file to predict: test_pic/cat.jpeg 33 | Predicted: [('n02124075', 'Egyptian_cat', 0.93183666)] 34 | ``` 35 | 36 | 37 | It will download weight file ``vgg19_weights_tf_dim_ordering_tf_kernels.h5`` and ``imagenet_class_index.json`` to ``~/.keras/models`` the first time. 38 | 39 | 40 | ## Compile 41 | 42 | ### use Makefile 43 | 44 | Using ``make all`` to Compile your cpp file. 45 | Make sure your python's version is correct. 46 | 47 | ``` 48 | bg@bg-cgi:~/.keras/models$ locate Python.h 49 | /usr/include/python2.7/Python.h 50 | /usr/include/python3.5m/Python.h 51 | ``` 52 | 53 | 54 | so I use the following cmd to compile 55 | 56 | ``` 57 | g++ -std=c++11 -Wall -O3 prediction.cpp -lpython3.5m -L/usr/include/python3.5m/ -I/usr/include/python3.5m/ -o pred_test 58 | ``` 59 | 60 | ### use Cmake 61 | 62 | I just write a ``CMakeLists.txt``, which can help you to compile your cpp code. 63 | So just use the following cmd: 64 | 65 | 66 | ``` 67 | mkdir build && cd build 68 | cmake ../ 69 | make 70 | cd ../ 71 | ``` 72 | 73 | Then you will see a executable file ``classifier``, just use ``./classifier`` to run the program. 74 | 75 | 76 | 77 | ## Usage 78 | 79 | ### Makefile 80 | 81 | ``make all`` to compile, then ``./pred_test`` to run c++ program. 82 | 83 | ### Cmake 84 | 85 | use ``./classifier`` to run the program after building. 86 | 87 | Then you can see it works: 88 | 89 | ``` 90 | ===========> START CALL PYTHON SCRIPT <=========== 91 | ===========> 1st CALL <=========== 92 | Please input picture file to predict: huhu 93 | file not exist! 94 | ===========> 2nd CALL <=========== 95 | Please input picture file to predict: test_pic/cat.jpeg 96 | Predicted: [('n02124075', 'Egyptian_cat', 0.93183666)] 97 | ===========> 3rd CALL <=========== 98 | Please input picture file to predict: test_pic/tiger.jpeg 99 | Predicted: [('n02129604', 'tiger', 0.82598984)] 100 | ===========> 4th CALL <=========== 101 | Please input picture file to predict: test_pic/puzzle.jpeg 102 | Predicted: [('n03598930', 'jigsaw_puzzle', 0.99813461)] 103 | ===========> CALLING FINISHED <=========== 104 | (deeplearning) bg@bg-cgi:~/Desktop/C_python$ 105 | ``` 106 | 107 | 108 | Feel free to contact me if you have any question. 109 | --------------------------------------------------------------------------------