Skip to content

Commit

Permalink
Merge pull request #4 from Lauszus/camera
Browse files Browse the repository at this point in the history
Allow the user to use the back camera as well
  • Loading branch information
Lauszus authored Mar 11, 2017
2 parents 1907b44 + 92d156a commit 27e825e
Show file tree
Hide file tree
Showing 13 changed files with 130 additions and 19 deletions.
9 changes: 5 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ android:
- extra-android-m2repository

before_script:
- git clone --depth 1 https://github.com/urho3d/android-ndk.git
- export ANDROID_NDK_HOME=$(pwd)/android-ndk
- wget https://dl.google.com/android/repository/android-ndk-r14-linux-x86_64.zip
- unzip -q android-ndk-r14-linux-x86_64.zip
- export ANDROID_NDK_HOME=$(pwd)/android-ndk-r14
- wget https://github.com/opencv/opencv/releases/download/3.1.0/OpenCV-3.1.0-android-sdk.zip
- unzip OpenCV-3.1.0-android-sdk.zip
- unzip -q OpenCV-3.1.0-android-sdk.zip
- export OPENCV_ANDROID_SDK=$(pwd)/OpenCV-android-sdk
- wget https://bitbucket.org/eigen/eigen/get/3.3.0.zip -O Eigen3.zip
- unzip Eigen3.zip
- unzip -q Eigen3.zip
- export EIGEN3_DIR=$(dirname $(find $(pwd) -type f -name 'signature_of_eigen3_matrix_library' -print -quit))

script:
Expand Down
3 changes: 2 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ android {
targetSdkVersion 24
versionCode 1
versionName '1.0'
vectorDrawables.useSupportLibrary = true
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64', 'x86'
stl 'gnustl_static'
cFlags '-std=gnu++11 -fexceptions -frtti'
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/cpp/Application.mk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
APP_PLATFORM := android-24
APP_ABI := armeabi-v7a arm64-v8a x86_64
APP_ABI := armeabi-v7a arm64-v8a x86_64 x86
APP_STL := gnustl_static
APP_CPPFLAGS := -std=gnu++11 -frtti -fexceptions

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/cpp/FaceRecognitionLib
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ public CameraBridgeViewBase(Context context, AttributeSet attrs) {
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
}

public void flipCamera() {
disableView();
if (this.mCameraIndex == CAMERA_ID_FRONT)
setCameraIndex(CAMERA_ID_BACK);
else
setCameraIndex(CAMERA_ID_FRONT);
enableView();
}

/**
* Sets the camera index
* @param cameraIndex new camera index
Expand Down Expand Up @@ -405,7 +414,7 @@ private float getRatio(int widthSource, int heightSource, int widthTarget, int h
* @return True if the app is running on an emulator.
*/
public boolean isEmulator() {
return Build.BRAND.equalsIgnoreCase("generic") || Build.BRAND.equalsIgnoreCase("android");
return Build.BRAND.equalsIgnoreCase("generic") || Build.BRAND.equalsIgnoreCase("generic_x86") || Build.BRAND.equalsIgnoreCase("android");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
package com.lauszus.facerecognitionapp;

import android.Manifest;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
Expand All @@ -39,6 +42,8 @@
import android.support.v7.widget.Toolbar;
import android.text.InputType;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
Expand Down Expand Up @@ -84,6 +89,7 @@ public class FaceRecognitionAppActivity extends AppCompatActivity implements Cam
private float faceThreshold, distanceThreshold;
private SharedPreferences prefs;
private TinyDB tinydb;
private Toolbar mToolbar;

private void showToast(String message, int duration) {
if (duration != Toast.LENGTH_SHORT && duration != Toast.LENGTH_LONG)
Expand Down Expand Up @@ -247,11 +253,11 @@ protected void onCreate(Bundle savedInstanceState) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

setContentView(R.layout.activity_face_recognition_app);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar); // Sets the Toolbar to act as the ActionBar for this Activity window
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar); // Sets the Toolbar to act as the ActionBar for this Activity window

DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, mToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();

Expand Down Expand Up @@ -309,13 +315,16 @@ public void onClick(View v) {
Log.i(TAG, "Cleared training set");
images.clear(); // Clear both arrays, when new instance is created
imagesLabels.clear();
showToast("Training set cleared", Toast.LENGTH_SHORT);
}
});

findViewById(R.id.take_picture_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(TAG, "Gray height: " + mGray.height() + " Width: " + mGray.width() + " total: " + mGray.total());
if (mGray.total() == 0)
return;
Size imageSize = new Size(200, 200.0f / ((float) mGray.width() / (float) mGray.height())); // Scale image in order to decrease computation time
Imgproc.resize(mGray, mGray, imageSize);
Log.i(TAG, "Small gray height: " + mGray.height() + " Width: " + mGray.width() + " total: " + mGray.total());
Expand Down Expand Up @@ -358,6 +367,7 @@ else if (minDist < distanceThreshold) // 3. Distant from face space and near a f
});

mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.camera_java_surface_view);
mOpenCvCameraView.setCameraIndex(prefs.getInt("mCameraIndex", CameraBridgeViewBase.CAMERA_ID_FRONT));
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
}
Expand Down Expand Up @@ -403,6 +413,7 @@ public void onStop() {
editor.putFloat("faceThreshold", faceThreshold);
editor.putFloat("distanceThreshold", distanceThreshold);
editor.putBoolean("useEigenfaces", useEigenfaces);
editor.putInt("mCameraIndex", mOpenCvCameraView.mCameraIndex);
editor.apply();

// Store ArrayLists containing the images and labels
Expand Down Expand Up @@ -487,11 +498,15 @@ public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
switch (orientation) {
case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
Core.flip(mRgba, mRgba, 0); // Flip along x-axis
if (mOpenCvCameraView.mCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT)
Core.flip(mRgba, mRgba, 0); // Flip along x-axis
else
Core.flip(mRgba, mRgba, -1); // Flip along both axis
break;
case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
Core.flip(mRgba, mRgba, 1); // Flip along y-axis
if (mOpenCvCameraView.mCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT)
Core.flip(mRgba, mRgba, 1); // Flip along y-axis
break;
}
}
Expand Down Expand Up @@ -529,4 +544,60 @@ public void onBackPressed() {
else
super.onBackPressed();
}

@SuppressLint("ApplySharedPref")
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_face_recognition_app, menu);
final MenuItem menuItem = menu.findItem(R.id.flip_camera);
View v = mToolbar.findViewById(R.id.flip_camera);
if (v != null) { // This will be null, when the menu is first created
// flipCamera() has already been called, so the index has already been changed
// We only set this here, so it does not use the default icon when inflating the menu
if (mOpenCvCameraView.mCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT)
menuItem.setIcon(R.drawable.ic_camera_front_white_24dp);
else
menuItem.setIcon(R.drawable.ic_camera_rear_white_24dp);
ObjectAnimator animator = ObjectAnimator.ofFloat(v, "rotationY", v.getRotationY() + 180.0f);
animator.setDuration(500);
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
// When the icon has been rotated, then change the icon
if (mOpenCvCameraView.mCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT)
menuItem.setIcon(R.drawable.ic_camera_rear_white_24dp);
else
menuItem.setIcon(R.drawable.ic_camera_front_white_24dp);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animator.start();
} else {
// Show rear camera icon if front camera is currently used and front camera icon if back camera is used
if (mOpenCvCameraView.mCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT)
menuItem.setIcon(R.drawable.ic_camera_rear_white_24dp);
else
menuItem.setIcon(R.drawable.ic_camera_front_white_24dp);
}
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.flip_camera:
mOpenCvCameraView.flipCamera();
supportInvalidateOptionsMenu();
return true;
}
return super.onOptionsItemSelected(item);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ protected boolean initializeCamera(int width, int height) {
synchronized (this) {
mCamera = null;

if (mCameraIndex == CAMERA_ID_ANY) {
if (mCameraIndex == CAMERA_ID_ANY || isEmulator()) { // Just open any camera on emulators
Log.d(TAG, "Trying to open camera with old open()");
try {
mCamera = Camera.open();
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_camera_front_white_24dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@android:color/white"
android:pathData="M10,20L5,20v2h5v2l3,-3 -3,-3v2zM14,20v2h5v-2h-5zM12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -1.99,0.9 -1.99,2S10.9,8 12,8zM17,0L7,0C5.9,0 5,0.9 5,2v14c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2L19,2c0,-1.1 -0.9,-2 -2,-2zM7,2h10v10.5c0,-1.67 -3.33,-2.5 -5,-2.5s-5,0.83 -5,2.5L7,2z"/>
</vector>
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_camera_rear_white_24dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@android:color/white"
android:pathData="M10,20L5,20v2h5v2l3,-3 -3,-3v2zM14,20v2h5v-2h-5zM17,0L7,0C5.9,0 5,0.9 5,2v14c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2L19,2c0,-1.1 -0.9,-2 -2,-2zM12,6c-1.11,0 -2,-0.9 -2,-2s0.89,-2 1.99,-2 2,0.9 2,2C14,5.1 13.1,6 12,6z"/>
</vector>
3 changes: 0 additions & 3 deletions app/src/main/res/layout/app_bar_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:CameraBridgeViewBase="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".FaceRecognitionAppActivity">

<!--CameraBridgeViewBase:show_fps="true"-->
<com.lauszus.facerecognitionapp.JavaCameraView
CameraBridgeViewBase:camera_id="front"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/camera_java_surface_view" />
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/res/menu/menu_face_recognition_app.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".FaceRecognitionAppActivity" >

<item
android:id="@+id/flip_camera"
android:title="@string/flip"
android:icon="@drawable/ic_camera_rear_white_24dp"
app:showAsAction="always" />

</menu>
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
<string name="threshold_face">Face threshold:</string>
<string name="threshold_distance">Distance threshold:</string>
<string name="clear_button">Clear training set</string>
<string name="flip">Flip</string>
</resources>
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Mon Dec 28 10:00:20 PST 2015
#Fri Mar 10 11:57:57 CET 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip

0 comments on commit 27e825e

Please sign in to comment.