使用Java api 和 jni混合方式调用OpenCV

from: http://blog.csdn.net/lingyun_blog/article/details/50733331

    int a =b;  


如果想在项目中直接使用opencv的java api 并且也需要自己编写c++,那么就需要Java Api与Jni混用,下面就以人脸检测为例,实验一些混合方式
一、创建项目
     创建项目FaceDetection


二、添加opencv的java api
     1、再项目中创建文件夹libopencv用来存放opencv的库module
     2、将 Android/OpenCV-android-sdk/sdk/java 复制到libopencv目录中,并将其改名opencv
 
     3、打开settings.gradle添加 include   ':libopencv:opencv并点击Sync Now
     4、在opencv中创建build.gradle文件,并将以下内容复制进去,注意按要求 替换内容然后点击Sync Now
apply plugin:'android-library'

buildscript{
    repositories{
        mavenCentral()
    }
    dependencies{
        classpath 'com.android.tools.build:gradle:1.3.0' // 和项目/build.gradle中的一致
    }
}

android{
    compileSdkVersion 22           //与 app/build.gradle中的一致
    buildToolsVersion "22.0.1"       //与 app/build.gradle中的一致

    defaultConfig {
        minSdkVersion 15             //与 app/build.gradle中的一致
        targetSdkVersion 22         //与 app/build.gradle中的一致
        versionCode 2411           //改成自己下的opencv的版本
        versionName "2.4.11"       //改成自己下的opencv的版本
    }

    sourceSets{
        main{
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            res.srcDirs = ['res']
            aidl.srcDirs = ['src']
        }
    }
}
      5、为app添加opencv依赖,在app上右键 open module settings,将opencv加进去

     
三、添加Opencv Face Detection Jni
1、打开opencv提供的人脸识别示例,将samples/face-detectioin/src/org/opencv/samples/facedetect/DetectionBasedTracker.java文件拷贝到app中包下,注意java文件package修改成当前的包
     错误是因为并没有native文件与之关联
     2、在app中创建autojavah.sh文件,用来创建jni文件夹及.h文件,内容如下:

#!/bin/sh
export ProjectPath=$(cd "../$(dirname "$1")"pwd)
export TargetClassName="com.lingyun.facedetection.DetectionBasedTracker" #换成你的包名.含有native方法的类名
export SourceFile="${ProjectPath}/app/src/main/java"   #java源文件目录
export TargetPath="${ProjectPath}/app/src/main/jni"     #输出jni文件目录
cd "${SourceFile}"
javah -d ${TargetPath} -classpath "${SourceFile}" "${TargetClassName}"
echo -d ${TargetPath} -classpath 
"${SourceFile}" "${TargetClassName}"

     3、右键运行autojavah.sh文件,如果没有插件,android Studio会提示是否下载安装插件
          此时可以看到多了jni目录以及一个.h文件

     4、将 OpenCV-android-sdk/samples/face-detection/jni中的.cpp 和.mk文件复制到jni目录中
          修改.cpp中的include头文件 #include <com_lingyun_facedetection_DetectionBasedTracker.h>
          修改函数名为.h中的函数名,这里有6个函数
          修改Android.mk文件:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=off
OPENCV_LIB_TYPE:=STATIC
下面一行换成自己的opencvsdk
include /Users/lichuanpeng/Documents/Program_File/Android/OpenCV-android-sdk/sdk/native/jni/OpenCV.mk
LOCAL_SRC_FILES  := DetectionBasedTracker_jni.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_LDLIBS     += -lm -llog
LOCAL_MODULE     := detection_based_tracker
include $(BUILD_SHARED_LIBRARY)
          修改Application.mk文件
APP_STL:=gnustl_static
APP_CPPFLAGS:=-frtti -fexceptions
APP_ABI := armeabi armeabi-v7a x86 mips
APP_PLATFORM := android-8

     5、配置app的build.gradle
          我的配置是
apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.lingyun.facedetecttest"
        minSdkVersion 15
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
          这是添加的
        ndk{
            moduleName "app"
        }
    }
      这是添加的
    sourceSets.main {
        jniLibs.srcDir 'src/main/jnilibs'
        jni.srcDirs = [] //disable automatic ndk-build call
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22+'
    compile project(':opencvlibs:opencv')
}


     6、新增NDK_BUILD 工具
          点击Android Studio->Preferences->External Tools 点击+新增
新增 NDK Build
Name: NDK Build
Group: NDK
Description: NDK Build
Options: 全打勾
Show in: 全打勾
Tools Settings:
Program: NDK目錄/ndk-build
Parameters: NDK_PROJECT_PATH=$ModuleFileDir$/build/intermediates/ndk NDK_LIBS_OUT=$ModuleFileDir$/src/main/jniLibs NDK_APPLICATION_MK=$ModuleFileDir$/src/main/jni/Application.mk APP_BUILD_SCRIPT=$ModuleFileDir$/src/main/jni/Android.mk V=1
Working directory: $SourcepathEntry$ 

     7、在app上右键点击NDK NDK Build
          可以看到多出来jniLibs目录
     8、将 OpenCV-android-sdk/sdk/native/libs  目录里面四个文件夹中的libopencv_java.so分别对应放在刚才生成的目录中,因为java api需要这些。

四、添加布局文件及activity和权限
     1、将 OpenCV-android-sdk/samples/face-detection/res/layout/face_detect_surface_view.xml 文件复制到app中的layout目录中
     2、在res中创建raw目录,并将 OpenCV-android-sdk/samples/face-detection/res/raw/lbpcascade_frontalface.xml 文件复制到raw中
     3、修改MainActivity      


  1. import java.io.File;  
  2. import java.io.FileOutputStream;  
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5.   
  6. import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;  
  7. import org.opencv.android.OpenCVLoader;  
  8. import org.opencv.core.Core;  
  9. import org.opencv.core.Mat;  
  10. import org.opencv.core.MatOfRect;  
  11. import org.opencv.core.Rect;  
  12. import org.opencv.core.Scalar;  
  13. import org.opencv.core.Size;  
  14. import org.opencv.android.CameraBridgeViewBase;  
  15. import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;  
  16. import org.opencv.objdetect.CascadeClassifier;  
  17.   
  18. import android.content.Context;  
  19. import android.os.Bundle;  
  20. import android.support.v7.app.AppCompatActivity;  
  21. import android.util.Log;  
  22. import android.view.Menu;  
  23. import android.view.MenuItem;  
  24. import android.view.WindowManager;  
  25. import com.lingyun.facedetection.R;  
  26.   
  27. public class MainActivity extends AppCompatActivity implements CvCameraViewListener2{  
  28.   
  29.     private static final String    TAG                 = "OCVSample::Activity";  
  30.     private static final Scalar    FACE_RECT_COLOR     = new Scalar(02550255);  
  31.     public static final int        JAVA_DETECTOR       = 0;  
  32.     public static final int        NATIVE_DETECTOR     = 1;  
  33.   
  34.     private MenuItem               mItemFace50;  
  35.     private MenuItem               mItemFace40;  
  36.     private MenuItem               mItemFace30;  
  37.     private MenuItem               mItemFace20;  
  38.     private MenuItem               mItemType;  
  39.   
  40.     private Mat                    mRgba;  
  41.     private Mat                    mGray;  
  42.     private File                   mCascadeFile;  
  43.     private CascadeClassifier      mJavaDetector;  
  44.     private DetectionBasedTracker  mNativeDetector;  
  45.   
  46.     private int                    mDetectorType       = JAVA_DETECTOR;  
  47.     private String[]               mDetectorName;  
  48.   
  49.     private float                  mRelativeFaceSize   = 0.2f;  
  50.     private int                    mAbsoluteFaceSize   = 0;  
  51.   
  52.     private CameraBridgeViewBase   mOpenCvCameraView;  
  53.   
  54.     static {  
  55.         if(!OpenCVLoader.initDebug()){  
  56.             Log.d("MyDebug","Falied");  
  57.         }else{  
  58.             Log.d("MyDebug","success");  
  59.             System.loadLibrary("opencv_java");  
  60.         }  
  61.     }  
  62.   
  63.     public void doDetect(){  
  64.         // Load native library after(!) OpenCV initialization  
  65.         System.loadLibrary("detection_based_tracker");//  
  66.   
  67.         try {  
  68.             // load cascade file from application resources  
  69.             InputStream is = getResources().openRawResource(R.raw.lbpcascade_frontalface);  
  70.             File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);  
  71.             mCascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");  
  72.             FileOutputStream os = new FileOutputStream(mCascadeFile);  
  73.   
  74.             byte[] buffer = new byte[4096];  
  75.             int bytesRead;  
  76.             while ((bytesRead = is.read(buffer)) != -1) {  
  77.                 os.write(buffer, 0, bytesRead);  
  78.             }  
  79.             is.close();  
  80.             os.close();  
  81.   
  82.             mJavaDetector = new CascadeClassifier(mCascadeFile.getAbsolutePath());  
  83.             if (mJavaDetector.empty()) {  
  84.                 Log.e(TAG, "Failed to load cascade classifier");  
  85.                 mJavaDetector = null;  
  86.             } else  
  87.                 Log.i(TAG, "Loaded cascade classifier from " + mCascadeFile.getAbsolutePath());  
  88.   
  89.             mNativeDetector = new DetectionBasedTracker(mCascadeFile.getAbsolutePath(), 0);  
  90.   
  91.             cascadeDir.delete();  
  92.   
  93.         } catch (IOException e) {  
  94.             e.printStackTrace();  
  95.             Log.e(TAG, "Failed to load cascade. Exception thrown: " + e);  
  96.         }  
  97.   
  98.         mOpenCvCameraView.enableView();  
  99.     }  
  100.   
  101.     public MainActivity() {  
  102.         mDetectorName = new String[2];  
  103.         mDetectorName[JAVA_DETECTOR] = "Java";  
  104.         mDetectorName[NATIVE_DETECTOR] = "Native (tracking)";  
  105.   
  106.         Log.i(TAG, "Instantiated new " + this.getClass());  
  107.     }  
  108.   
  109.     /** Called when the activity is first created. */  
  110.     @Override  
  111.     public void onCreate(Bundle savedInstanceState) {  
  112.         Log.i(TAG, "called onCreate");  
  113.         super.onCreate(savedInstanceState);  
  114.         getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);  
  115.   
  116.         setContentView(R.layout.face_detect_surface_view);  
  117.   
  118.         mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.fd_activity_surface_view);  
  119.         mOpenCvCameraView.setCvCameraViewListener(this);  
  120.         doDetect();  
  121.     }  
  122.   
  123.     @Override  
  124.     public void onPause()  
  125.     {  
  126.         super.onPause();  
  127.         if (mOpenCvCameraView != null)  
  128.             mOpenCvCameraView.disableView();  
  129.     }  
  130.   
  131.     @Override  
  132.     public void onResume()  
  133.     {  
  134.         super.onResume();  
  135.         // OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);  
  136.     }  
  137.   
  138.     public void onDestroy() {  
  139.         super.onDestroy();  
  140.         mOpenCvCameraView.disableView();  
  141.     }  
  142.   
  143.     public void onCameraViewStarted(int width, int height) {  
  144.         mGray = new Mat();  
  145.         mRgba = new Mat();  
  146.     }  
  147.   
  148.     public void onCameraViewStopped() {  
  149.         mGray.release();  
  150.         mRgba.release();  
  151.     }  
  152.   
  153.     public Mat onCameraFrame(CvCameraViewFrame inputFrame) {  
  154.   
  155.         mRgba = inputFrame.rgba();  
  156.         mGray = inputFrame.gray();  
  157.   
  158.         if (mAbsoluteFaceSize == 0) {  
  159.             int height = mGray.rows();  
  160.             if (Math.round(height * mRelativeFaceSize) > 0) {  
  161.                 mAbsoluteFaceSize = Math.round(height * mRelativeFaceSize);  
  162.             }  
  163.             mNativeDetector.setMinFaceSize(mAbsoluteFaceSize);  
  164.         }  
  165.   
  166.         MatOfRect faces = new MatOfRect();  
  167.   
  168.         if (mDetectorType == JAVA_DETECTOR) {  
  169.             if (mJavaDetector != null)  
  170.                 mJavaDetector.detectMultiScale(mGray, faces, 1.122// TODO: objdetect.CV_HAAR_SCALE_IMAGE  
  171.                         new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size());  
  172.         }  
  173.         else if (mDetectorType == NATIVE_DETECTOR) {  
  174.             if (mNativeDetector != null)  
  175.                 mNativeDetector.detect(mGray, faces);  
  176.         }  
  177.         else {  
  178.             Log.e(TAG, "Detection method is not selected!");  
  179.         }  
  180.   
  181.         Rect[] facesArray = faces.toArray();  
  182.         for (int i = 0; i < facesArray.length; i++)  
  183.             Core.rectangle(mRgba, facesArray[i].tl(), facesArray[i].br(), FACE_RECT_COLOR, 3);  
  184.   
  185.         return mRgba;  
  186.     }  
  187.   
  188.     @Override  
  189.     public boolean onCreateOptionsMenu(Menu menu) {  
  190.         Log.i(TAG, "called onCreateOptionsMenu");  
  191.         mItemFace50 = menu.add("Face size 50%");  
  192.         mItemFace40 = menu.add("Face size 40%");  
  193.         mItemFace30 = menu.add("Face size 30%");  
  194.         mItemFace20 = menu.add("Face size 20%");  
  195.         mItemType   = menu.add(mDetectorName[mDetectorType]);  
  196.         return true;  
  197.     }  
  198.   
  199.     @Override  
  200.     public boolean onOptionsItemSelected(MenuItem item) {  
  201.         Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);  
  202.         if (item == mItemFace50)  
  203.             setMinFaceSize(0.5f);  
  204.         else if (item == mItemFace40)  
  205.             setMinFaceSize(0.4f);  
  206.         else if (item == mItemFace30)  
  207.             setMinFaceSize(0.3f);  
  208.         else if (item == mItemFace20)  
  209.             setMinFaceSize(0.2f);  
  210.         else if (item == mItemType) {  
  211.             int tmpDetectorType = (mDetectorType + 1) % mDetectorName.length;  
  212.             item.setTitle(mDetectorName[tmpDetectorType]);  
  213.             setDetectorType(tmpDetectorType);  
  214.         }  
  215.         return true;  
  216.     }  
  217.   
  218.     private void setMinFaceSize(float faceSize) {  
  219.         mRelativeFaceSize = faceSize;  
  220.         mAbsoluteFaceSize = 0;  
  221.     }  
  222.   
  223.     private void setDetectorType(int type) {  
  224.         if (mDetectorType != type) {  
  225.             mDetectorType = type;  
  226.   
  227.             if (type == NATIVE_DETECTOR) {  
  228.                 Log.i(TAG, "Detection Based Tracker enabled");  
  229.                 mNativeDetector.start();  
  230.             } else {  
  231.                 Log.i(TAG, "Cascade detector enabled");  
  232.                 mNativeDetector.stop();  
  233.             }  
  234.         }  
  235.     }  
  236.      }  

     4、添加摄像机权限
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.lingyun.facedetection" >  
  4.   
  5.     <application  
  6.         android:allowBackup="true"  
  7.         android:icon="@mipmap/ic_launcher"  
  8.         android:label="@string/app_name"  
  9.         android:theme="@style/AppTheme" >  
  10.         <activity  
  11.             android:name=".MainActivity"  
  12.             android:label="@string/app_name" >  
  13.             <intent-filter>  
  14.                 <action android:name="android.intent.action.MAIN" />  
  15.   
  16.                 <category android:name="android.intent.category.LAUNCHER" />  
  17.             </intent-filter>  
  18.         </activity>  
  19.     </application>  
  20.     <supports-screens android:resizeable="true"  
  21.         android:smallScreens="true"  
  22.         android:normalScreens="true"  
  23.         android:largeScreens="true"  
  24.         android:anyDensity="true" />  
  25.   
  26.     <uses-sdk android:minSdkVersion="8" />  
  27.   
  28.     <uses-permission android:name="android.permission.CAMERA"/>  
  29.   
  30.     <uses-feature android:name="android.hardware.camera" android:required="false"/>  
  31.     <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>  
  32.     <uses-feature android:name="android.hardware.camera.front" android:required="false"/>  
  33.     <uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>  
  34.   
  35. </manifest>  

五、调试
     运行项目
   







     
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值