在 Android 裡面有兩種寫 OpenCV 的方法:
一種是用 C++ 的語法寫,包給 java 用(參考這篇)。
這篇寫另外一種用 java 的語法呼叫 OpenCV 的函式寫。
測試的環境:
1. Android Studio 版本為 3.0.1 (Android Studio 載點)。
2. OpenCV SDK for Android 版本為 2.4.11 (OpenCV SDK 載點)
建立一個 Android 專案,在目錄中建立 libraries 資料夾,將 SDK 那包的 \sdk\java 整個資料夾複製到 libraries 裡面,把 java 資料夾重新命名為 opencv,接著在 opencv 資料夾內建立一個build.gradle 檔案。
build.gradle:
其中這三個是依照版本而改
- apply plugin: 'android-library'
- buildscript {
- repositories {
- mavenCentral()
- }
- dependencies {
- classpath 'com.android.tools.build:gradle:3.0.1'
- }
- }
- android {
- compileSdkVersion 26
- defaultConfig {
- minSdkVersion 15
- targetSdkVersion 26
- }
- sourceSets {
- main {
- manifest.srcFile 'AndroidManifest.xml'
- java.srcDirs = ['src']
- resources.srcDirs = ['src']
- res.srcDirs = ['res']
- aidl.srcDirs = ['src']
- }
- }
- }
classpath 'com.android.tools.build:gradle:3.0.1
compileSdkVersion 26
targetSdkVersion 26
接著在 settings.gradle 裡面加入
- include ':libraries:opencv'
設定 File>Project Structure>app>Dependencies,加入 Module dependency,選擇libraries:opencv。
再來,在專案中建立一個 jniLibs 資料夾,並且把 SDK 中的 \sdk\native\libs 複製過去。
到這裡,先 Rebuild 整個專案看看是否成功。
在做到這裏的時候有可能出現錯誤訊息:
Error: A problem occurred starting process 'command 'C:\Users\Chris\AppData\Local\Android\sdk\ndk-bundle\toolchains\mips64el-linux-android-4.9\prebuilt\windows-x86_64\bin\mips64el-linux-android-strip'‘
解決方法: SDK Manager > SDK Tools tab > uncheck NDK > Apply and OK
準備就緒之後,就可以開始來寫一個,將攝影機的影像轉成灰階 (RGB to Gray) 的程式了。
在 xml 加入 JavaCameraView 來秀攝影機畫面
- <org.opencv.android.JavaCameraView
- android:id="@+id/id_opencvView"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- tools:layout_editor_absoluteX="0dp"
- tools:layout_editor_absoluteY="0dp" />
在 MainActivity.java 引入:
- public class OpenCVClass implements CameraBridgeViewBase.CvCameraViewListener2{
- private Mat mRgbCamMat, mGrayMat; // Create a mat
- @Override
- public void onCameraViewStarted(int width, int height) {
- mRgbCamMat = new Mat();
- mGrayMat = new Mat();
- }
- @Override
- public void onCameraViewStopped() {
- mRgbCamMat.release();
- mGrayMat.release();
- }
- @Override
- public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
- mRgbCamMat = inputFrame.rgba(); // get camera image
- Imgproc.cvtColor(mRgbCamMat , mGrayMat, Imgproc.COLOR_RGB2GRAY); // in java
- return mGrayMat; // return camera image mat
- }
- }
在 AndroidManifest.xml 加入開啟攝影機的權限
- private CameraBridgeViewBase mOpenCvCameraView; // view to show camera image
- private OpenCVClass mOpenCVClass; // your opencv class
- @Override
- protected void onCreate(){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.id_opencvView);
- mOpenCVClass = new OpenCVClass();
- mOpenCvCameraView.setCvCameraViewListener(mOpenCVClass);
- }
- @Override
- public void onPause(){
- super.onPause();
- if (mOpenCvCameraView != null)
- mOpenCvCameraView.disableView();
- }
- @Override
- public void onResume(){
- super.onResume();
- if (!OpenCVLoader.initDebug()) {
- // load opencv tool
- OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_11, this, mLoaderCallback);
- } else {
- mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
- }
- }
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (mOpenCvCameraView != null)
- mOpenCvCameraView.disableView();
- }
- private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
- @Override
- public void onManagerConnected(int status) {
- switch (status) {
- case LoaderCallbackInterface.SUCCESS:
- mOpenCvCameraView.enableView();
- break;
- default:
- super.onManagerConnected(status);
- break;
- }
- }
- };
程式執行後會發現攝影機的畫面被轉了 90 度,修正方法在 AndroidManifest.xml 把 app 設定成橫向就好了
- <uses-permission android:name="android.permission.CAMERA"/>
- <activity android:name=".MainActivity"
- android:screenOrientation="landscape">
執行後就會看到正確的攝影機畫面轉成灰階了。
另外有一些常用的 OpenCV 函式,如果要用可以參考看看:
如果要把 Mat 轉成 java 的 view 元件,可以用以下方法轉換
- Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2GRAY);
- Imgproc.threshold(dst, dst, Threshold ,255, Imgproc.THRESH_BINARY);
- Imgproc.Canny(src, dst, 100, 200);
- Imgproc.dilate(dst, dst, new Mat());
- Imgproc.findContours(dst, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
以上是用 java 的語法寫 OpenCV 的方法
- Bitmap bm = Bitmap.createBitmap(resultMat.cols(), resultMat.rows(), Bitmap.Config.ARGB_8888);
- Utils.matToBitmap(resultMat, bm);
(END)
沒有留言:
張貼留言