java和C++采用JNI的方式进行接口传参交互。
C++中或者C#等.net都能生成.dll类库,而C++(或.net)中生成的.dll文件,相当于java程序中java源代码通过编译生成的.class文件,我们在java程序中直接通过code调用C++的dll文件即可。
函数声明:
1 2 3 4 5 6 7 8 |
HJRecMethod ptrRecFunc = 0; extern "C" { JNIEXPORT jint JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_IntialAlg(JNIEnv*, jobject, jint val ); JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_ReleaseAlg(JNIEnv*, jobject ); JNIEXPORT jint JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_FaceExtract(JNIEnv*, jobject , jlong addrGray , jlong addrRGB, jfloatArray ptrfeat); JNIEXPORT jfloat JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_CalcDisC(JNIEnv*, jobject , jfloatArray x , jfloatArray y , jint dims ); JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba); } |
注意:在JNI中的声明.cpp中和.h中的方法名一定要相同!!!并且把从java中找到的jni.h 和jni_md.h粘贴到外部依赖文件夹。
1 2 3 4 |
//JNI中声明 JNIEXPORT jint JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_IntialAlg(JNIEnv*, jobject, jint val ); // public native int IntialAlg(int val); |
函数定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
//Main Function Implementation extern "C" { JNIEXPORT jint JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_IntialAlg(JNIEnv*, jobject, jint val ){ Mat maskgray = Mat::zeros( 128 , 128 , CV_8UC1); IplImage iplgray = maskgray; HJLoadMask( &iplgray ); for ( int i = 0 ; i < _HJMaxCam ; i++ ){ maskimg[i] = cvCreateImage( cvSize(128,128) , 8 ,1 ); cvCopyImage( &iplgray , maskimg[i] ); //T.copyTo(FrTrain[i]); hjfacedet[i] = HJInitFaceDetect( hjfacedet[ i ] ); //v5.0 InitEyeLoc( &lefteyeloc[ i ]); hjmem[ i ].Create(); } ptrRecFunc = FeatExtraU264; algval = 1; return 2891; } |
在Activity主函数中去进行开发
1 2 3 4 5 |
public native void FindFeatures(long matAddrGr, long matAddrRgba); public native int IntialAlg(int val); public native void ReleaseAlg(); public native int FaceExtract(long matAddrGr , long matAddrRgba ,float[] ptrfeat); public native float CalcDisC(float[] ptrfeat1 , float[] ptrfeat2 , int dims ); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
//继承自Activity类 public class Tutorial2Activity extends Activity implements CvCameraViewListener2 { private static final String TAG = "OCVSample::Activity"; private static final int VIEW_MODE_FaceReg = 2; private static final int VIEW_MODE_FaceRec = 5; private int mViewMode;//通过改变这个值来切换模式 private Mat mRgba; private Mat mIntermediateMat; private Mat mGray; private View cameraView, landView; private CameraBridgeViewBase mOpenCvCameraView; //async initialization //http://docs.opencv.org/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.html private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { @Override public void onManagerConnected(int status) { switch (status) { case LoaderCallbackInterface.SUCCESS: { Log.i(TAG, "OpenCV loaded successfully"); // Load native library after(!) OpenCV initialization System.loadLibrary("mixed_sample"); mOpenCvCameraView.enableView(); } break; default: { super.onManagerConnected(status); } break; } } }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
//Create函数 @Override public void onCreate(Bundle savedInstanceState) { Log.i(TAG, "called onCreate"); super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setContentView(R.layout.tutorial2_surface_view);//这个函数就是把界面上的一些东西显示出来 View btn1 = this.findViewById(R.id.btn_vc); btn1.setOnClickListener(new ButtonClickListener()); //ButtonClickLisener 去监听消息,在不断地执行 View btn2 = this.findViewById(R.id.btn_reg); btn2.setOnClickListener(new ButtonClickListener()); View btn3 = this.findViewById(R.id.btn_rec); btn3.setOnClickListener(new ButtonClickListener()); mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial2_activity_surface_view); mOpenCvCameraView.setCvCameraViewListener(this); mOpenCvCameraView.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_FRONT); } public Mat onCameraFrame(CvCameraViewFrame inputFrame) { float[] x = new float[2891]; if ( alg == 0 ){ algsuc = IntialAlg(1); if ( algsuc==2891) Log.i(TAG, "Alg success!"); else Log.i(TAG, "Alg failed!"); alg++; } final int viewMode = mViewMode; mRgba = inputFrame.rgba(); mGray = inputFrame.gray(); switch (viewMode) { case VIEW_MODE_FaceReg: for ( int i = 0 ; i < 2891 ; i++ ){ x[i] = 0; } if ( valreg > 0 ) { int res = FaceExtract(mGray.getNativeObjAddr(),mRgba.getNativeObjAddr() , x ); if ( res == 1 ){ valreg--; if ( valreg == 0 ) { for ( int i = 0 ; i < 2891 ; i++ ) { gx[i]=x[i]; } } } } break; case VIEW_MODE_FaceRec: for ( int i = 0 ; i < 2891 ; i++ ){ x[i] = 0; } //FindFeatures(mGray.getNativeObjAddr(), mRgba.getNativeObjAddr()); int res = FaceExtract(mGray.getNativeObjAddr(),mRgba.getNativeObjAddr() , x ); if ( res == 1 ){ float disC = CalcDisC( x , gx , 2891 ); if ( disC > 0.7 ){ Intent intent = new Intent(); intent.setClass(Tutorial2Activity.this, com.camera.simplemjpeg.MjpegActivity.class); startActivity(intent); } } break; } return mRgba; } private class ButtonClickListener implements View.OnClickListener{ public void onClick(View v) { if(R.id.btn_vc == v.getId()){ Intent intent = new Intent();//意图,去打开一个新的页面 intent.setClass(Tutorial2Activity.this, com.camera.simplemjpeg.Land.class); startActivity(intent); } else if(R.id.btn_reg == v.getId()){ valreg = 10; mViewMode = VIEW_MODE_FaceReg; } else if(R.id.btn_rec == v.getId()){ mViewMode = VIEW_MODE_FaceRec; } } } |
Ref:http://docs.opencv.org/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.html