Android—基於OpenCV+Android實現人臉檢測


導讀

OpenCV 是一個開源的跨平台計算機視覺庫, 采C++語言編寫,實現了圖像處理和計算機視覺方面的很多通用算法,同時也提供對Python,Java,Android等的支持,這里利用Android下的接口,實現一個簡單的人臉檢測;

首先需要說清楚這里是人臉檢測,不是人臉識別,網上很多資料說實現人臉識別,最后一看明明是人臉檢測。
人臉檢測:是找出人臉,並標記出人臉。
人臉識別:檢測出人臉,並能夠通過學習,給出人臉信息,比如,給定一個人臉A,通過學習,在之后的眾多檢測中能夠找出人臉A,這才是人臉識別;

准備工作

首先到http://opencv.org/releases.html下載相應的開發工具,我下載時latest version是3.4.1,選擇Android pack。開發包比較大,我下載時已經300多M。下載后解壓縮,得到如下目錄結構;

新建AS項目,OpenCVDemo,然后File > New > New Module,選擇Import Eclipse ADT Project;
把下載下來的目錄下sdk/java 下的項目導入到項目里。此時生產的Module名稱為openCVLibrary2411,版本不同這里名字會不同,后面添加依賴時,需要注意!

然后將剛新建的這個modules 添加依賴到 app modules里,
直接在 app 目錄下build.gradle 文件里dependencies 下添加:

compile project(':openCVLibrary2411')

然后在 app/src/main 目錄下創建一個jniLibs 目錄,然后把sdk/native/libs 下全部文件 copy到jniLibs下,編譯通過。

修改新建模塊下 build.gradle 文件,把 compileSdkVersion 與 targetSdkVersion修改成你最新的SDK版本,如我的:

apply plugin: 'com.android.library'

android {
    compileSdkVersion 27
    buildToolsVersion "26.0.2"

    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 27
    }

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

我app下的build.gradle文件如下:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.jiajia.opencvdemo"
        minSdkVersion 21
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

    implementation project(':openCVLibrary2411')
}

OK, 上面就是所有的准備工作;

實現人臉檢測

只需要有一個MainActivity即可,首先申請相應的權限

    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-feature android:name="android.hardware.camera" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>

如果是Android是6.0以上,調用相機需要動態申請權限(小Demo,我直接在設置中為應用賦予了權限);

修改MainActivity代碼如下:

public class MainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener{

    private CameraBridgeViewBase openCvCameraView;
    private CascadeClassifier cascadeClassifier;
    private Mat grayscaleImage;
    private int absoluteFaceSize;
    private void initializeOpenCVDependencies() {
        try {
            InputStream is = getResources().openRawResource(R.raw.lbpcascade_frontalface);
            File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
            File mCascadeFile = new File(cascadeDir, "lbpcascade_frontalface.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();
            cascadeClassifier = new CascadeClassifier(mCascadeFile.getAbsolutePath());
        } catch (Exception e) {
            Log.e("OpenCVActivity", "Error loading cascade", e);
        }
        openCvCameraView.enableView();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        openCvCameraView = new JavaCameraView(this, -1);    // 新建一個布局文件
        setContentView(openCvCameraView);   // 為該活動設置布局
        openCvCameraView.setCvCameraViewListener(this);

    }
    @Override
    public void onCameraViewStarted(int width, int height) {
        grayscaleImage = new Mat(height, width, CvType.CV_8UC4);
        absoluteFaceSize = (int) (height * 0.2);
    }

    @Override
    public void onCameraViewStopped() {
    }

    @Override
    public Mat onCameraFrame(Mat aInputFrame) {
        Imgproc.cvtColor(aInputFrame, grayscaleImage, Imgproc.COLOR_RGBA2RGB);
        MatOfRect faces = new MatOfRect();
        if (cascadeClassifier != null) {
            cascadeClassifier.detectMultiScale(grayscaleImage, faces, 1.1, 2, 2,
                    new Size(absoluteFaceSize, absoluteFaceSize), new Size());
        }
        Rect[] facesArray = faces.toArray();
        for (int i = 0; i <facesArray.length; i++)
            Core.rectangle(aInputFrame, facesArray[i].tl(), facesArray[i].br(), new Scalar(0, 255, 0, 255), 3);
        return aInputFrame;
    }
    @Override
    public void onResume() {
        super.onResume();

        if (!OpenCVLoader.initDebug()) {
        }
        initializeOpenCVDependencies();
    }
}

簡單分析:

首先onCreate方法中設置屏幕常亮.

getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

然后新建了一個布局openCvCameraView,這個布局文件是OpenCV封裝好了,不需要我們重寫布局文件,因為請看setContentView方法,這和平時我們寫Activity是不一樣的。

openCvCameraView = new JavaCameraView(this, -1);    // 新建一個布局文件
setContentView(openCvCameraView);   // 為該活動設置布局

然后為這個布局類設置了回調監聽, 因為我們的MainActivity實現了CameraBridgeViewBase.CvCameraViewListener,所以監聽器就是本身;

openCvCameraView.setCvCameraViewListener(this);

實現了該監聽器,就需要實現onCameraViewStarted onCameraViewStopped onCameraFrame這三個方法,具體實現的邏輯就在這三個方法中,涉及到很多數據知識,就不多說了(我也不是很懂!!!)

參考資料

  1. Android 接入 OpenCV庫的三種方式

最后

  • 本文內容個人拙見,若有出入,歡迎指正。
  • 歡迎賞臉關注:家佳Talk

歡迎賞臉關注:家佳Talk


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM