Android OpenCV環境搭建與Demo展示


title: Android OpenCV環境搭建與Demo展示
tags: Opencv
date: 2020-2-02 00:53:00


最終效果

在這裏插入圖片描述

視頻展示:

https://www.bilibili.com/video/av86393649/

【Android opencv】硬件工程師假期無聊硬擼安卓opencv開發

【Android opencv】優化動態修改參數UI

前言:

首先,這個項目說實話我做了兩年,上學的時候很想做這個東西,由於當時能力不足,對於編程方面的知識儲備也不足,而且對於未知的東西有種渴望,但是無奈心有餘而力不足,導致自己的很多想法都放棄了,有些甚至夭折了。

環境配置:

Android studio版本:V3.5.2
OpenCV版本:3.4.6
接下來我將逐一給大家截圖分析環境的搭建過程,後面應該還會錄製一期視頻來講解。
資料下載:
工程倉庫地址:
https://github.com/az666/Android-Opencv
opencv-3.4.6-android-sdk.zip
https://download.csdn.net/download/switch_love_case/12129739
SO庫:libopencv_info.so (用於免Manager APP) https://download.csdn.net/download/wawayuchibang/10614343
博主APK文件: https://fir.im/ve24

備註: 下面的所有流程成立的前提是你的AndroidStudio能夠正常工作!即代表你的AndroidStudio的運行環境是OK的。不然後面出現問題不好排查。



  1. 首先,在你的Android Studio能正常工作的前提下,新建一個項目,注意新版的Android Studio
    是可以直接新建C++依賴的。

在這裏插入圖片描述

在這裏插入圖片描述

  1. 注意這裏要選擇C++14

在這裏插入圖片描述

  1. 到這裏如果編譯無錯,證明你的Android Studio是可以正常運行的(如果有錯誤,需要你自己排查下,因爲版本不同,我不在講解錯誤排查),可以暫停一下,由於OpenCV需要NDK和Cmake支持,這裏需要配置一下,勾選下載即可。

在這裏插入圖片描述

OpenCV—JAVA庫安裝

  1. 接下來開始安裝Opencv庫支持
    在這裏插入圖片描述
  2. 導入剛剛下載的opencvSDK裏面的JAVA庫
    在這裏插入圖片描述
    在這裏插入圖片描述
    在這裏插入圖片描述
  3. 這個時候,等待初始化完成,不出意外地話 應該會報錯:
    刪除掉報錯的那一行即可,因爲新版的Android Studio已經不允許在First文件裏聲明最小版本了,刪除即可。
    在這裏插入圖片描述

OpenCV—JAVA庫依賴

  1. 下面開始添加依賴

在這裏插入圖片描述
在這裏插入圖片描述

致此,已基本配置OK

OpenCV—免Manger APP配置

  1. 官方的Opencv Android支持是需要配合另外一個APP來實現的圖像處理,這樣使用起來很不友好,接下來進行移植。 按照圖中文件路徑,將文件夾下所有文件拷貝至 jniLibs文件夾下(如果沒有自己新建一個)

在這裏插入圖片描述

人臉級聯分類庫移植

  1. 將下載的SDK文件夾下(G:\2019_AI_learn\opencv-3.4.6-android-sdk\OpenCV-android-sdk\sdk\etc\lbpcascades)的人臉數據拷貝至如圖路徑下的raw文件夾(新建一個)下即可。
    在這裏插入圖片描述

最終測試代碼移植與調試

MainActivity.java代碼:

public class MainActivity extends AppCompatActivity implements
        CameraBridgeViewBase.CvCameraViewListener2, View.OnClickListener {

    private CameraBridgeViewBase cameraView;
    private CascadeClassifier classifier;
    private Mat mGray;
    private Mat mRgba;
    private int mAbsoluteFaceSize = 0;
    private boolean isFrontCamera;

    // 手動裝載openCV庫文件,以保證手機無需安裝OpenCV Manager   不加這裏將導致無法初始化 級聯分類器(開機閃退)
    static {
        System.loadLibrary("opencv_java3");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA}, 1);
        }
        initWindowSettings();
        setContentView(R.layout.activity_main);
        cameraView = (CameraBridgeViewBase) findViewById(R.id.camera_view);
        cameraView.setCvCameraViewListener(this); // 設置相機監聽
        initClassifier();
        cameraView.enableView();
        Button switchCamera = (Button) findViewById(R.id.switch_camera);
        switchCamera.setOnClickListener(this); // 切換相機鏡頭,默認後置
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.switch_camera:
                cameraView.disableView();
                if (isFrontCamera) {
                    cameraView.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_BACK);
                    isFrontCamera = false;
                } else {
                    cameraView.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_FRONT);
                    isFrontCamera = true;
                }
                cameraView.enableView();
                break;
            default:
        }
    }

    // 初始化窗口設置, 包括全屏、橫屏、常亮
    private void initWindowSettings() {
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }

    // 初始化人臉級聯分類器,必須先初始化
    private void initClassifier() {
        try {
            InputStream is = getResources()
                    .openRawResource(R.raw.lbpcascade_frontalface);
            File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
            File cascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");
            FileOutputStream os = new FileOutputStream(cascadeFile);
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            is.close();
            os.close();
            classifier = new CascadeClassifier(cascadeFile.getAbsolutePath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onCameraViewStarted(int width, int height) {
        mGray = new Mat();
        mRgba = new Mat();
    }

    @Override
    public void onCameraViewStopped() {
        mGray.release();
        mRgba.release();
    }

    @Override
    // 這裏執行人臉檢測的邏輯, 根據OpenCV提供的例子實現(face-detection)
    public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
        mRgba = inputFrame.rgba();
        mGray = inputFrame.gray();
        // 翻轉矩陣以適配前後置攝像頭
        if (isFrontCamera) {
            Core.flip(mRgba, mRgba, 1);
            Core.flip(mGray, mGray, 1);
        } else {
            //如果發現後攝出現了鏡像  把下面的註釋打開即可  魅族不需要
//            Core.flip(mRgba, mRgba, -1);
//            Core.flip(mGray, mGray, -1);
        }
        float mRelativeFaceSize = 0.2f;
        if (mAbsoluteFaceSize == 0) {
            int height = mGray.rows();
            if (Math.round(height * mRelativeFaceSize) > 0) {
                mAbsoluteFaceSize = Math.round(height * mRelativeFaceSize);
            }
        }
        MatOfRect faces = new MatOfRect();
        if (classifier != null)
            classifier.detectMultiScale(mGray, faces, 1.1, 2, 2,
                    new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size());
        Rect[] facesArray = faces.toArray();
        Scalar faceRectColor = new Scalar(0, 255, 0, 255);
        for (Rect faceRect : facesArray)
            Imgproc.rectangle(mRgba, faceRect.tl(), faceRect.br(), faceRectColor, 3);
        return mRgba;
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (cameraView != null) {
            cameraView.disableView();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        cameraView.disableView();
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 &&
                        grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                } else {
                    Toast.makeText(this, "權限拒絕", Toast.LENGTH_SHORT).show();
                }
        }
    }
}

activity_main.xml代碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">
    <org.opencv.android.JavaCameraView
        android:id="@+id/camera_view"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"/>
    <Button
        android:layout_margin="10dp"
        android:text="'皮'"
        android:id="@+id/switch_camera"
        android:layout_width="43dp"
        android:layout_height="37dp"
        android:layout_gravity="center_vertical" />
</LinearLayout>

接下來不出意外地話,代碼錯誤會比較少,如下:
是由於依賴庫衝突導致,利用快捷鍵更改爲Opencv即可。
在這裏插入圖片描述
修改完以後編譯,直接真機調試,會出現下圖錯誤,原因爲Opencv庫的版本(過低)或者與本APP版本不一致,修改一下即可
在這裏插入圖片描述

APP真機安裝調試

在這裏插入圖片描述
在這裏插入圖片描述

致此,所有流程完畢。後續會有更詳細的視頻講解。
物聯網學習羣:476840321
UP博客: http://wenzheng.club

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章