打開新手教程,找到sdk的下載地址 java
當前最新版本是3.4.2 android
下載便可 c++
2.勾選C++14支持和其餘兩個選項 app
3.等待初始化完成ide
4.配置NDK和CMAKE支持 打開File->Settings..., 在SDK Tools下方勾選CMAKE和NDK, Android Studio會自動下載CMAKE和NDK 函數
5.引入opencv測試
打開File->Project Structure... 點擊 Import Module gradle
選擇opencv安裝目錄的sdk/java
的目錄 ui
修改Compile Sdk Version 與app 一致, 打開File->Project Structure... app的版本是 API 28 this
opencv的版本也須要設置爲 API 28
app添加opencv module
拷貝opencv安裝目錄下的sdk\native\jni\include
文件夾到工程目錄下面的app/src/main/cpp
目錄下
拷貝opencv安裝目錄下的sdk\native\libs
文件夾到工程目錄下面的app/src/main/jniLibs
目錄下
app/build.gradle
在android節點下面添加
sourceSets{ main{ jniLibs.srcDirs = ['src/main/jniLibs/libs'] } }
修改androiddefaultConfigcmake/externalNativeBuild/cmake
節點
externalNativeBuild { cmake { cppFlags "-std=c++14 -frtti -fexceptions " arguments '-DANDROID_STL=gnustl_static' abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } }
app/CMakeLists.txt
在cmake_minimum_required(VERSION 3.4.1)
下方插入
# 添加opencv的頭文件目錄 include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include) # 導入opencv的so add_library(libopencv_java3 SHARED IMPORTED) set_target_properties(libopencv_java3 PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/libs/${ANDROID_ABI}/libopencv_java3.so)
修改target_link_libraries
target_link_libraries( # Specifies the target library. native-lib libopencv_java3 # 連接opencv的so # Links the target library to the log library # included in the NDK. ${log-lib} )
修改class MainActivity
在onCreate
函數末尾添加以下代碼,須要先import org.opencv.core.Mat;
Mat mImg = new Mat(); mImg.release();
若是app可以在手機上正常運行說明配置成功
首先得拷貝opencv安裝目錄下的sdk\etc\haarcascades\haarcascade_frontalface_default.xml
文件到工程目錄app\src\main\res\raw
下
native-lib.cpp
#include <jni.h> #include <string> #include <opencv2/opencv.hpp> static cv::CascadeClassifier* face_detecter = nullptr; // 初始化分類器 extern "C" JNIEXPORT void JNICALL Java_com_xiong_dalton_cvcamerafacedetection_MainActivity_FaceDetecterInit( JNIEnv *jenv, jobject /* this */, jstring cascadeFileName ){ const char* cascade_file_name = jenv->GetStringUTFChars(cascadeFileName, NULL); if( face_detecter == nullptr){ face_detecter = new cv::CascadeClassifier(cascade_file_name); } } // 找出人臉所在位置並標記出來 extern "C" JNIEXPORT void JNICALL Java_com_xiong_dalton_cvcamerafacedetection_MainActivity_DetectFaces( JNIEnv /* *env */, jobject /* this */, jlong addrInputRgbaImage ) { cv::Mat& image_input = *(cv::Mat*)addrInputRgbaImage; cv::Mat image_gray; cv::cvtColor(image_input, image_gray, cv::COLOR_RGBA2GRAY); auto width = image_input.size().width; auto height = image_input.size().height; if(face_detecter != nullptr){ std::vector<cv::Rect> faces; face_detecter->detectMultiScale( image_gray, faces, 1.1, 2, 0|cv::CASCADE_SCALE_IMAGE, cv::Size(width/10, height/5)); for(auto face_rect: faces){ cv::rectangle(image_input, face_rect, cv::Scalar(255, 0, 0), 3); } } }
MainActivity.java
package com.xiong.dalton.cvcamerafacedetection; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.SurfaceView; import android.view.WindowManager; import org.opencv.android.BaseLoaderCallback; import org.opencv.android.CameraBridgeViewBase; import org.opencv.android.LoaderCallbackInterface; import org.opencv.android.OpenCVLoader; import org.opencv.core.Mat; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; public class MainActivity extends Activity implements CameraBridgeViewBase.CvCameraViewListener2 { static final String TAG = "MainActivity"; CameraBridgeViewBase mOpenCvCameraView; File mCascadeFile; Mat mRgba; static { System.loadLibrary("native-lib"); } private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { @Override public void onManagerConnected(int status) { switch (status) { case LoaderCallbackInterface.SUCCESS: { Log.i(TAG, "OpenCV loaded successfully"); // 使用opencv自帶的分類器文件初始化 try{ InputStream is = getResources().openRawResource(R.raw.haarcascade_frontalface_default); File cascadeDir = getDir("cascade", Context.MODE_PRIVATE); mCascadeFile = new File(cascadeDir, "haarcascade_frontalface_default.xml"); FileOutputStream os = new FileOutputStream(mCascadeFile); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = is.read(buffer)) != -1) { os.write(buffer, 0, bytesRead); } is.close(); os.close(); FaceDetecterInit(mCascadeFile.getAbsolutePath()); //調用jni的初始化接口 cascadeDir.delete(); } catch (IOException e){ e.printStackTrace(); Log.e(TAG, "Failed to load cascade. Exception thrown: " + e); } mOpenCvCameraView.enableView(); } break; default: { super.onManagerConnected(status); } } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setContentView(R.layout.activity_main); mOpenCvCameraView = findViewById(R.id.cameraView); mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE); mOpenCvCameraView.setCvCameraViewListener(this); mOpenCvCameraView.enableFpsMeter(); //顯示fps信息 } @Override public void onPause() { super.onPause(); disableCamera(); } @Override public void onResume() { super.onResume(); if (!OpenCVLoader.initDebug()) { Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization"); OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback); } else { Log.d(TAG, "OpenCV library found inside package. Using it!"); mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS); } } public void onDestroy() { super.onDestroy(); disableCamera(); } public void disableCamera() { if (mOpenCvCameraView != null) mOpenCvCameraView.disableView(); } public void onCameraViewStarted(int width, int height) { } public void onCameraViewStopped() { } public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) { mRgba = inputFrame.rgba(); DetectFaces(mRgba.getNativeObjAddr()); return mRgba; } public native long FaceDetecterInit(String cascadeFileName); public native long DetectFaces(long addrInputRgbaImage); }