Liunx python呼び出しc++ライブラリ(クラス、関数)、転送パラメータ
一、c++を使用してダイナミックライブラリをカプセル化する
参考文献:http://www.linuxidc.com/Linux/2012-09/70502.htm
1.testクラスの新規作成
1.1 testを新規作成する.cppファイル
コードは次のとおりです.
#include
extern "C"
int myadd(int a, int b)
{
return a + b;
}
備考:extern「C」は必ずあります.そうしないとundefined symbol:myadd.
1.2 testを新規作成する.hファイル
コードは次のとおりです.
#ifndef _TESTSO_H
#define_TESTSO_H
extern"C"
{
intmyadd(int a, int b);
typedefint myadd_t(int, int);//myadd function type
}
#endif//_TESTSO_H
備考:test.hファイルはtestのためなくてもいいです.cppも#includeがなく、myadd()関数もクラスのメンバー関数ではありません.
2.コンパイル
g++ -shared -fPIC -o test.so test.cpp
メモ1:
-L path:pathディレクトリでライブラリファイルを検索することを示します.例えば-L.は現在のディレクトリに表示されます.
-I path:pathディレクトリでヘッダファイルを検索することを示します.
-o file:出力ファイルをfileとします.
メモ2:
複数のcppファイルをコンパイルするには:
g++ -shared-fPIC -o demo.so demo.cpp CCNF_patch_expert.cpp LandmarkDetectorFunc.cppLandmarkDetectorModel.cpp LandmarkDetectorUtils.cppLandmarkDetectorParameters.cpp LandmarkDetectionValidator.cpp Patch_experts.cppPAW.cpp PDM.cpp SVR_patch_expert.cpp stdafx.cpp$(pkg-config opencv --cflags --libs) $(/usr/lib/x86_64-linux-gnu/libboost_filesystem.so;/usr/lib/x86_64-linux-gnu/libboost_system.so)-I/usr/include/boost -L/usr/lib/x86_64-linux-gnu/-I boost_system –l boost_filesystem
(上記のコマンドコードを使用してコンパイルする場合は、まずコードをtxtに入れて1行に書き、最後にコマンドラインに値を付けてコンパイルします.そうしないとエラーになる可能性があります)
あ、makefileファイルを書いてコンパイルしたほうがいいです.
3.C++方式呼び出しライブラリ
3.1新規main.cpp
コードは次のとおりです.
3.2コンパイル
g++ main.cpp -o main -ldl
メモ:-ldlパラメータがない場合は、undefinedreference to`dlopen'エラー解決が報告されます.
3.3運転
./main test.so
4.Python方式呼び出しライブラリ
4.1新規main.py
from ctypesimport *
#loaddll and get the function object
dll= cdll.LoadLibrary(’/landmark/LandmarkDetector/test.so');
t= dll.myadd(1,2)
print(t)
4.2運転
python main.py
二、python調c++ライブラリ、そして伝出パラメータ
2.1 c++ライブラリ関数
例:
c++ライブラリ関数:
inttest(const cv::Mat img, conststd::vector<:rect> vRect, const std::string sModelPath, cv::Vec3f&pose)
パラメータを入力:
const cv::Matimg:ピクチャデータ
constststd::vector<:rect>vRect:顔領域
const std::stringsModelPath:モデルパス
出力パラメータ:
cv::Vec 3 f&pose:顔角度(x,y,z)
python,c++は2つの異なるプログラミング言語であるため,相互呼び出し時にデータ型を相手が認めるものに変換する必要がある.
2.2入力パラメータ
2.2.1 const cv::Matimgパラメータ修正
参考文献:http://bbs.csdn.net/topics/340060802
C++ライブラリ部分
1.const cv::Matimgパラメータを(int*img,int rows,int cols,int channels)に変更
2.int*img画像データをcv::Matimgに解析する.
コードは次のとおりです.
Python呼び出し部
コードは次のとおりです.
src= cv2.imread("/OpenFace-master/test/face_0.jpg") #0 - gray
cols= src.shape[1]
rows =src.shape[0]
channels= 0
if 3==len(src.shape):
channels= 3
src= np.asarray(src,dtype=np.int)#定義されたint*imgタイプと一致する必要があります
src1 = src.ctypes.data_as(ctypes.c_char_p)#多次元配列をchar*に変換
t =dll.test(src1, rows, cols, channels)
コメント:
src = np.array([[11,22],[3,4]])
src1 = src.ctypes.data_as(ctypes.c_char_p)
t = dll.test(src1, rows, cols, channels)
c++のsrc 1の数値は以下の通りです.
matrix[0] = 11
matrix[1] = 0
matrix[2]= 22
matrix[3]= 0
matrix[4]= 3
matrix[5]= 0
matrix[6]= 4
matrix[7] = 0
2.2.2 const cv::vector<:rect>vRectパラメータ修正
c++ライブラリ部分
1.const cv::vector<:rect>vRectパラメータを(int*rect,int num)に変更
2.int*rect顔領域データをcv::vector<:rect>vRect;
コードは次のとおりです.
Python呼び出し部
コードは次のとおりです.
num=1#人の顔領域を表す個数
rect = np.zeros((num,4),dtype=np.int)#4人の顔領域を表す(x,y,w,h)
rect[0][0] = 0
rect[0][1] = 0
rect[0][2] = cols-1
rect[0][3] = rows-1
#print (src.dtype) #uint8
rect = np.asarray(rect, dtype=np.int)
#print (src.dtype) #int64
rect1 = rect.ctypes.data_as(ctypes.c_char_p)
t = dll.test(src1, rows, cols, channels, rect1, num)
メモ:floatタイプの場合、c_を使用する必要があります.float(cx)変換後、入力するとokになります.そうしないと、タイプが一致しません.
2.3出力パラメータ
参考文献:http://blog.csdn.net/uniqsa/article/details/78603082
2.3.1 cv::Vec 3 f&poseパラメータ修正
c++ライブラリ部分
1.cv::Vec 3 f&poseパラメータをstruHeadPose&poseに変更する.
2.test.cppでstruHeadPose構造体を定義します.
structstruHeadPose
{
float angleX;
float angleY;
float angleZ;
};
3.struHeadPose poseは値を割り当てて返します.
pose.angleX = angleX;
pose.angleY = angleY;
pose.angleZ= angleZ;
python呼び出しセクション
コードは次のとおりです.
参考文献:http://www.linuxidc.com/Linux/2012-09/70502.htm
1.testクラスの新規作成
1.1 testを新規作成する.cppファイル
コードは次のとおりです.
#include
extern "C"
int myadd(int a, int b)
{
return a + b;
}
備考:extern「C」は必ずあります.そうしないとundefined symbol:myadd.
1.2 testを新規作成する.hファイル
コードは次のとおりです.
#ifndef _TESTSO_H
#define_TESTSO_H
extern"C"
{
intmyadd(int a, int b);
typedefint myadd_t(int, int);//myadd function type
}
#endif//_TESTSO_H
備考:test.hファイルはtestのためなくてもいいです.cppも#includeがなく、myadd()関数もクラスのメンバー関数ではありません.
2.コンパイル
g++ -shared -fPIC -o test.so test.cpp
メモ1:
-fPIC: , ;
-L path:pathディレクトリでライブラリファイルを検索することを示します.例えば-L.は現在のディレクトリに表示されます.
-I path:pathディレクトリでヘッダファイルを検索することを示します.
-o file:出力ファイルをfileとします.
-shared: ;
メモ2:
複数のcppファイルをコンパイルするには:
g++ -shared-fPIC -o demo.so demo.cpp CCNF_patch_expert.cpp LandmarkDetectorFunc.cppLandmarkDetectorModel.cpp LandmarkDetectorUtils.cppLandmarkDetectorParameters.cpp LandmarkDetectionValidator.cpp Patch_experts.cppPAW.cpp PDM.cpp SVR_patch_expert.cpp stdafx.cpp$(pkg-config opencv --cflags --libs) $(/usr/lib/x86_64-linux-gnu/libboost_filesystem.so;/usr/lib/x86_64-linux-gnu/libboost_system.so)-I/usr/include/boost -L/usr/lib/x86_64-linux-gnu/-I boost_system –l boost_filesystem
(上記のコマンドコードを使用してコンパイルする場合は、まずコードをtxtに入れて1行に書き、最後にコマンドラインに値を付けてコンパイルします.そうしないとエラーになる可能性があります)
あ、makefileファイルを書いてコンパイルしたほうがいいです.
3.C++方式呼び出しライブラリ
3.1新規main.cpp
コードは次のとおりです.
#include
#include //
#include
#include"test.h" // for dynamic library
int main(int argc, char*argv[])
{
if (2 != argc)
{
return-1;
}
const char *soname =argv[1];
void *so_handle = dlopen(soname,RTLD_LAZY); // .so
if (!so_handle)
{
fprintf(stderr,"Error: load so `%s' failed./n", soname);
return-1;
}
dlerror(); //
myadd_t *fn =(myadd_t*)dlsym(so_handle,"myadd"); //
char *err =dlerror();
if (NULL != err)
{
fprintf(stderr,"%s/n", err);
return-1;
}
printf("myadd57 + 3 = %d/n", fn(57, 3)); //
dlclose(so_handle);// so
return 0;
}
3.2コンパイル
g++ main.cpp -o main -ldl
メモ:-ldlパラメータがない場合は、undefinedreference to`dlopen'エラー解決が報告されます.
3.3運転
./main test.so
4.Python方式呼び出しライブラリ
4.1新規main.py
from ctypesimport *
#loaddll and get the function object
dll= cdll.LoadLibrary(’/landmark/LandmarkDetector/test.so');
t= dll.myadd(1,2)
print(t)
4.2運転
python main.py
二、python調c++ライブラリ、そして伝出パラメータ
2.1 c++ライブラリ関数
例:
c++ライブラリ関数:
inttest(const cv::Mat img, conststd::vector<:rect> vRect, const std::string sModelPath, cv::Vec3f&pose)
パラメータを入力:
const cv::Matimg:ピクチャデータ
constststd::vector<:rect>vRect:顔領域
const std::stringsModelPath:モデルパス
出力パラメータ:
cv::Vec 3 f&pose:顔角度(x,y,z)
python,c++は2つの異なるプログラミング言語であるため,相互呼び出し時にデータ型を相手が認めるものに変換する必要がある.
2.2入力パラメータ
2.2.1 const cv::Matimgパラメータ修正
参考文献:http://bbs.csdn.net/topics/340060802
C++ライブラリ部分
1.const cv::Matimgパラメータを(int*img,int rows,int cols,int channels)に変更
2.int*img画像データをcv::Matimgに解析する.
コードは次のとおりです.
cv::Mat show_matrix(int *matrix, int rows, int cols, int channels)
{
int i, j, c;
if (3==channels)
{
cv::Mat img(rows,cols,CV_8UC3,cv::Scalar(0,0,0));
std::cout<(0);
for (i=0; i(ii);
j = i%(cols*2*3)/2;
c = j%3;
j = j/3;
pxvec[j*3 + c] =(unsigned char)matrix[i];
//printf("pxvec[%d][%d][%d]= %d
", ii,j,c, matrix[i]);
}
}
return img;
}
else
{
cv::Mat img(rows,cols,CV_8UC1,cv::Scalar(0,0,0));
std::cout<(0);
for (i=0; i(ii);
j = i%(cols*2)/2;
pxvec[j] =(unsigned char)matrix[i];
//printf("pxvec[%d][%d]= %d
", ii, j, matrix[i]);
}
}
return img;
}
}
Python呼び出し部
コードは次のとおりです.
src= cv2.imread("/OpenFace-master/test/face_0.jpg") #0 - gray
cols= src.shape[1]
rows =src.shape[0]
channels= 0
if 3==len(src.shape):
channels= 3
src= np.asarray(src,dtype=np.int)#定義されたint*imgタイプと一致する必要があります
src1 = src.ctypes.data_as(ctypes.c_char_p)#多次元配列をchar*に変換
t =dll.test(src1, rows, cols, channels)
コメント:
src = np.array([[11,22],[3,4]])
src1 = src.ctypes.data_as(ctypes.c_char_p)
t = dll.test(src1, rows, cols, channels)
c++のsrc 1の数値は以下の通りです.
matrix[0] = 11
matrix[1] = 0
matrix[2]= 22
matrix[3]= 0
matrix[4]= 3
matrix[5]= 0
matrix[6]= 4
matrix[7] = 0
2.2.2 const cv::vector<:rect>vRectパラメータ修正
c++ライブラリ部分
1.const cv::vector<:rect>vRectパラメータを(int*rect,int num)に変更
2.int*rect顔領域データをcv::vector<:rect>vRect;
コードは次のとおりです.
vector<:rect> show_rect(int* rect, introws)
{
vector<:rec> vRect;
int cols = 4; //(x,y,w,h)
int i,j;
int x=0,y=0,w=0,h=0;
cv::Rect roi;
for (i=0; i
Python呼び出し部
コードは次のとおりです.
num=1#人の顔領域を表す個数
rect = np.zeros((num,4),dtype=np.int)#4人の顔領域を表す(x,y,w,h)
rect[0][0] = 0
rect[0][1] = 0
rect[0][2] = cols-1
rect[0][3] = rows-1
#print (src.dtype) #uint8
rect = np.asarray(rect, dtype=np.int)
#print (src.dtype) #int64
rect1 = rect.ctypes.data_as(ctypes.c_char_p)
t = dll.test(src1, rows, cols, channels, rect1, num)
メモ:floatタイプの場合、c_を使用する必要があります.float(cx)変換後、入力するとokになります.そうしないと、タイプが一致しません.
2.3出力パラメータ
参考文献:http://blog.csdn.net/uniqsa/article/details/78603082
2.3.1 cv::Vec 3 f&poseパラメータ修正
c++ライブラリ部分
1.cv::Vec 3 f&poseパラメータをstruHeadPose&poseに変更する.
2.test.cppでstruHeadPose構造体を定義します.
structstruHeadPose
{
float angleX;
float angleY;
float angleZ;
};
3.struHeadPose poseは値を割り当てて返します.
pose.angleX = angleX;
pose.angleY = angleY;
pose.angleZ= angleZ;
python呼び出しセクション
コードは次のとおりです.
class struHeadPose(ctypes.Structure):
_fields_ =[("angleX", ctypes.c_float),("angleY",ctypes.c_float),("angleZ", ctypes.c_float)]
pose =struHeadPose(0.0, 0.0, 0.0)
sModelPath ="/LandmarkDetector/model/main_clnf_general.txt"
t = dll.test(src1,rows, cols, channels, rect1, num, sModelPath, ctypes.byref(pose))
print(pose.angleX)
print(pose.angleY)
print(pose.angleZ)
、c++ 、python
:http://blog.csdn.net/wuchuanpingstone/article/details/77763455( )
3.1 c++
3.1.1 demo.h
#ifndef _DEMOSO_H
#define _DEMOSO_H
// OpenCV includes
#include
#include
#include
struct struHeadPose
{
float angleX;
float angleY;
float angleZ;
};
class CCaculateFaceAngle
{
public:
int getPose(int* imgData, int h, int w, int channels, float cx, float cy, float fx, float fy,struHeadPose& pose);
int LoadModel(char* sModelPath);
private:
LandmarkDetector::FaceModelParameters m_det_parameters;
LandmarkDetector::CLNF m_clnf_model;
};
#endif // _DEMOSO_H
3.1.2 demo.cpp
#include "demo.h"
int CCaculateFaceAngle::getPose(int* imgData, int h, int w, int channels, float cx, float cy, float fx, float fy, struHeadPose& pose)
{
}
int CCaculateFaceAngle::LoadModel(char* sModelPath)
{
}
// , c++ 。
extern "C"
{
CCaculateFaceAngle obj;
int getPose(int* imgData, int h, int w, int channels, float cx, float cy, float fx, float fy,struHeadPose& pose)
{
return obj.getPose(imgData, h, w, channels, cx, cy, fx, fy,pose);
}
int LoadModel(char* sModelPath)
{
return obj.LoadModel(sModelPath);
}
}
3.2 python c++
from ctypes import *
import cv2
import ctypes
import numpy as np
dll = cdll.LoadLibrary('/LandmarkDetector/class_so/demo.so');
# model path
sModelPath = "/LandmarkDetector/model/main_clnf_general.txt"
#image data
src = cv2.imread("/OpenFace-master/test/face_0.jpg") #0-gray
cols = src.shape[1]
rows = src.shape[0]
#print('img shape:{}'.format(src.shape))
channels = 0
if 3==len(src.shape):
channels = 3
src = np.asarray(src, dtype=np.int)
src1 = src.ctypes.data_as(ctypes.c_char_p)
#fx fy cx cy
cx = cols / 2.0
cy = rows / 2.0
fx = 500 * (cols / 640.0)
fy = 500 * (rows / 480.0)
fx = (fx + fy) / 2.0
fy = fx
cx1 = c_float(cx)
cy1 = c_float(cy)
fx1 = c_float(fx)
fy1 = c_float(fy)
#head pose
class struHeadPose(ctypes.Structure):
_fields_ = [("angleX", ctypes.c_float),("angleY", ctypes.c_float),("angleZ", ctypes.c_float)]
pose = struHeadPose(0.0, 0.0, 0.0)
if dll.LoadModel(sModelPath) > -1:
t = dll.getPose(src1, rows, cols, channels, cx1, cy1, fx1, fy1, ctypes.byref(pose))
print (pose.angleX)
print (pose.angleY)
print (pose.angleZ)