Liunx python呼び出しc++ライブラリ(クラス、関数)、転送パラメータ

12315 ワード

一、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:
-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)



liunx python  c++ ( 、  ),      _ 1