最近在做基於OpenCV的車牌識別, 其中需要用到深度學習的一些代碼(Python), 所以一開始的時候開發語言選擇了Python(禍患之源).
固然現在Python的速度不算太慢, 但你一定要用Python來操作圖像, 實現某些算法的時候, 效率就變得非常重要. 可惜的是, Python在大多數算法實現中, 由於其循環操作實在是太慢, 導致實現的算法效率非常之低.
所以現在我要把深度學習中的一個類(分類器)轉換到C++中, 在這個過程之前, 需要做一些test projects, 我主要參照的文章是: C++調用Python(3).
開發環境為 VS2012, WIN7 64.
所有代碼都在最后放出, 這里先逐步講解.
首先我們需要導入合適的頭文件: Python.h, 它位於你的Python安裝目錄的include目錄下. (2.6, 2.7版本實測通過)
使用VS的話, 可以按如下方法設置一下項目屬性:
- 調試 -> xxx屬性(最后一欄) -> VC++目錄 -> 右側庫目錄
- 增加C:\Python27\libs, 具體路徑個人可能不同.
這樣就完成了最基本的配置, 下面我們開始導入.py文件並使用它.
我們使用的.py文件非常簡單, 代碼如下:
1 #!/usr/bin/python
2 # Filename: testpy.py
3 class Person: 4 def sayHi(self): 5 print 'hi'
6 class Second: 7 def invoke(self,obj): 8 obj.sayHi() 9 def sayhi(name): 10 print 'hi',name;
注: 下述所有導入方法在導入失敗時不會報錯, 只會返回空指針.
第一步是導入.py文件:
- 使用PyObject* pModule來存儲導入的.py文件模塊, 調用的方法是PyImport_ImportModule(path): PyObject* pModule = PyImport_ImportModule("testpy");
- 使用PyObject* pDict來存儲導入模塊中的方法字典, 調用的方法是PyModule_GetDict(module): PyObject* pDict = PyModule_GetDict(pModule);
這樣就完成了.py文件的導入.
第二步是導入已導入模塊中的方法或類:
- 獲取方法, 調用的方法是PyDict_GetItemString(dict, methodName): PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi");
- 獲取類, 調用的方法同上, 注意紅體部分的字符串對應於.py文件中的類/方法名: PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second");
第三步是使用導入的方法或類:
- 使用方法, 調用PyObject_CallFunction(pFunc, "s", args)即可: PyObject_CallFunction(pFunHi, "s", "lhb");
- 使用類構造對象, 調用PyInstance_New(pClass, NULL, NULL)即可: PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL); , 注意其中的pClassSecond為第二步.2中獲取的類指針
- 使用類對象的方法, 調用PyObject_CallMethod(pInstance, methodname, "O", args)即可: PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson);
- 上述調用中的"s"和"O"代表的是參數列表的類型, 我們可以在 Py_BuildValue 找到所有的類型, 本文最后也附了此表.
最后不要忘記銷毀這些對象: Py_DECREF(pointer);
下面是C++的實現代碼, 代碼來自於我參考的博客, 略有修改.
1 /*
2 * test.cpp 3 * Created on: 2010-8-12 4 * Author: lihaibo 5 */
6 #include <C:/Python27/include/Python.h>
7 #include <iostream>
8 #include <string>
9
10 int main(void) { 11 Py_Initialize(); // 啟動虛擬機
12 if (!Py_IsInitialized()) 13 return -1; 14 // 導入模塊
15 PyObject* pModule = PyImport_ImportModule("testpy"); 16 if (!pModule) { 17 printf("Cant open python file!/n"); 18 return -1; 19 } 20 // 模塊的字典列表
21 PyObject* pDict = PyModule_GetDict(pModule); 22 if (!pDict) { 23 printf("Cant find dictionary./n"); 24 return -1; 25 } 26 // 演示函數調用
27 PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi"); 28 PyObject_CallFunction(pFunHi, "s", "lhb"); 29 Py_DECREF(pFunHi); 30 // 演示構造一個Python對象,並調用Class的方法 31 // 獲取Second類
32 PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second"); 33 if (!pClassSecond) { 34 printf("Cant find second class./n"); 35 return -1; 36 } 37 //獲取Person類
38 PyObject* pClassPerson = PyDict_GetItemString(pDict, "Person"); 39 if (!pClassPerson) { 40 printf("Cant find person class./n"); 41 return -1; 42 } 43 //構造Second的實例
44 PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL); 45 if (!pInstanceSecond) { 46 printf("Cant create second instance./n"); 47 return -1; 48 } 49 //構造Person的實例
50 PyObject* pInstancePerson = PyInstance_New(pClassPerson, NULL, NULL); 51 if (!pInstancePerson) { 52 printf("Cant find person instance./n"); 53 return -1; 54 } 55 //把person實例傳入second的invoke方法
56 PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson); 57 //釋放
58 Py_DECREF(pInstanceSecond); 59 Py_DECREF(pInstancePerson); 60 Py_DECREF(pClassSecond); 61 Py_DECREF(pClassPerson); 62 Py_DECREF(pModule); 63 Py_Finalize(); // 關閉虛擬機
64 return 0; 65 }
類型參照:
- s (string) [char *]
- Convert a null-terminated C string to a Python object. If the C string pointer is NULL, None is used.
- s# (string) [char *, int]
- Convert a C string and its length to a Python object. If the C string pointer is NULL, the length is ignored and None is returned.
- z (string or None) [char *]
- Same as s.
- z# (string or None) [char *, int]
- Same as s#.
- u (Unicode string) [Py_UNICODE *]
- Convert a null-terminated buffer of Unicode (UCS-2 or UCS-4) data to a Python Unicode object. If the Unicode buffer pointer is NULL, Noneis returned.
- u# (Unicode string) [Py_UNICODE *, int]
- Convert a Unicode (UCS-2 or UCS-4) data buffer and its length to a Python Unicode object. If the Unicode buffer pointer is NULL, the length is ignored and None is returned.
- i (integer) [int]
- Convert a plain C int to a Python integer object.
- b (integer) [char]
- Convert a plain C char to a Python integer object.
- h (integer) [short int]
- Convert a plain C short int to a Python integer object.
- l (integer) [long int]
- Convert a C long int to a Python integer object.
- B (integer) [unsigned char]
- Convert a C unsigned char to a Python integer object.
- H (integer) [unsigned short int]
- Convert a C unsigned short int to a Python integer object.
- I (integer/long) [unsigned int]
- Convert a C unsigned int to a Python integer object or a Python long integer object, if it is larger than sys.maxint.
- k (integer/long) [unsigned long]
- Convert a C unsigned long to a Python integer object or a Python long integer object, if it is larger than sys.maxint.
- L (long) [PY_LONG_LONG]
- Convert a C long long to a Python long integer object. Only available on platforms that support long long.
- K (long) [unsigned PY_LONG_LONG]
- Convert a C unsigned long long to a Python long integer object. Only available on platforms that support unsigned long long.
- n (int) [Py_ssize_t]
-
Convert a C Py_ssize_t to a Python integer or long integer.
New in version 2.5.
- c (string of length 1) [char]
- Convert a C int representing a character to a Python string of length 1.
- d (float) [double]
- Convert a C double to a Python floating point number.
- f (float) [float]
- Same as d.
- D (complex) [Py_complex *]
- Convert a C Py_complex structure to a Python complex number.
- O (object) [PyObject *]
- Pass a Python object untouched (except for its reference count, which is incremented by one). If the object passed in is a NULL pointer, it is assumed that this was caused because the call producing the argument found an error and set an exception. Therefore, Py_BuildValue()will return NULL but won’t raise an exception. If no exception has been raised yet, SystemError is set.
- S (object) [PyObject *]
- Same as O.
- N (object) [PyObject *]
- Same as O, except it doesn’t increment the reference count on the object. Useful when the object is created by a call to an object constructor in the argument list.
- O& (object) [converter, anything]
- Convert anything to a Python object through a converter function. The function is called with anything (which should be compatible withvoid *) as its argument and should return a “new” Python object, or NULL if an error occurred.
- (items) (tuple) [matching-items]
- Convert a sequence of C values to a Python tuple with the same number of items.
- [items] (list) [matching-items]
- Convert a sequence of C values to a Python list with the same number of items.
- {items} (dictionary) [matching-items]
- Convert a sequence of C values to a Python dictionary. Each pair of consecutive C values adds one item to the dictionary, serving as key and value, respectively.
If there is an error in the format string, the SystemError exception is set and NULL returned.