summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/ui/FaceView.java
diff options
context:
space:
mode:
authorIvan Evlogiev <ivanevlogiev@codeaurora.org>2014-02-17 12:08:12 +0200
committerIvan Evlogiev <ivanevlogiev@codeaurora.org>2014-03-11 11:11:14 -0700
commite64c0dd0ae60c2c0fb045e6bd059b71ae222baa0 (patch)
treea7ef5eba4e8400a888d70dd5de57ec311bd4a73c /src/com/android/camera/ui/FaceView.java
parentad9ab7b9644116721f658525a1253bf658361c6c (diff)
downloadandroid_packages_apps_Snap-e64c0dd0ae60c2c0fb045e6bd059b71ae222baa0.tar.gz
android_packages_apps_Snap-e64c0dd0ae60c2c0fb045e6bd059b71ae222baa0.tar.bz2
android_packages_apps_Snap-e64c0dd0ae60c2c0fb045e6bd059b71ae222baa0.zip
Camera: Add facial processing features
Add smile, gaze and blink detection features CRs-fixed: 531927 587195 Change-Id: I7e710e6d9038b14d00d77ea87f9b4c65baa74fc0
Diffstat (limited to 'src/com/android/camera/ui/FaceView.java')
-rw-r--r--src/com/android/camera/ui/FaceView.java122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/com/android/camera/ui/FaceView.java b/src/com/android/camera/ui/FaceView.java
index 1b3a9c72e..c89e14c82 100644
--- a/src/com/android/camera/ui/FaceView.java
+++ b/src/com/android/camera/ui/FaceView.java
@@ -21,6 +21,7 @@ import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.Color;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.hardware.Camera.Face;
@@ -33,6 +34,7 @@ import android.view.View;
import com.android.camera.PhotoUI;
import com.android.camera.util.CameraUtil;
import com.android.camera2.R;
+import org.codeaurora.camera.ExtendedFace;
public class FaceView extends View
implements FocusIndicator, Rotatable,
@@ -63,6 +65,11 @@ public class FaceView extends View
private int mUncroppedWidth;
private int mUncroppedHeight;
+
+ private final int smile_threashold_no_smile = 30;
+ private final int smile_threashold_small_smile = 60;
+ private final int blink_threshold = 60;
+
private static final int MSG_SWITCH_FACES = 1;
private static final int SWITCH_DELAY = 70;
private boolean mStateSwitchPending = false;
@@ -90,6 +97,9 @@ public class FaceView extends View
mPaint.setAntiAlias(true);
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeWidth(res.getDimension(R.dimen.face_circle_stroke));
+ mPaint.setDither(true);
+ mPaint.setColor(Color.WHITE);//setColor(0xFFFFFF00);
+ mPaint.setStrokeCap(Paint.Cap.ROUND);
}
@Override
@@ -215,6 +225,118 @@ public class FaceView extends View
mPaint.setColor(mColor);
mRect.offset(dx, dy);
canvas.drawOval(mRect, mPaint);
+ if (mFaces[i] instanceof ExtendedFace) {
+ ExtendedFace face = (ExtendedFace)mFaces[i];
+ float[] point = new float[4];
+ int delta_x = mFaces[i].rect.width() / 12;
+ int delta_y = mFaces[i].rect.height() / 12;
+ Log.e(TAG, "blink: (" + face.getLeftEyeBlinkDegree()+ ", " +
+ face.getRightEyeBlinkDegree() + ")");
+ if (face.leftEye != null) {
+ point[0] = face.leftEye.x + dx;
+ point[1] = face.leftEye.y-delta_y/2;
+ point[2] = face.leftEye.x;
+ point[3] = face.leftEye.y+delta_y/2;
+ mMatrix.mapPoints (point);
+ if (face.getLeftEyeBlinkDegree() >= blink_threshold) {
+ canvas.drawLine(point[0]+ dx, point[1]+ dy,
+ point[2]+ dx, point[3]+ dy, mPaint);
+ }
+ }
+ if (face.rightEye != null) {
+ point[0] = face.rightEye.x;
+ point[1] = face.rightEye.y-delta_y/2;
+ point[2] = face.rightEye.x;
+ point[3] = face.rightEye.y+delta_y/2;
+ mMatrix.mapPoints (point);
+ if (face.getRightEyeBlinkDegree() >= blink_threshold) {
+ //Add offset to the points if the rect has an offset
+ canvas.drawLine(point[0] + dx, point[1] + dy,
+ point[2] +dx, point[3] +dy, mPaint);
+ }
+ }
+
+ if (face.getLeftRightGazeDegree() != 0
+ || face.getTopBottomGazeDegree() != 0 ) {
+
+ double length =
+ Math.sqrt((face.leftEye.x - face.rightEye.x) *
+ (face.leftEye.x - face.rightEye.x) +
+ (face.leftEye.y - face.rightEye.y) *
+ (face.leftEye.y - face.rightEye.y)) / 2.0;
+ double nGazeYaw = -face.getLeftRightGazeDegree();
+ double nGazePitch = -face.getTopBottomGazeDegree();
+ float gazeRollX =
+ (float)((-Math.sin(nGazeYaw/180.0*Math.PI) *
+ Math.cos(-face.getRollDirection()/
+ 180.0*Math.PI) +
+ Math.sin(nGazePitch/180.0*Math.PI) *
+ Math.cos(nGazeYaw/180.0*Math.PI) *
+ Math.sin(-face.getRollDirection()/
+ 180.0*Math.PI)) *
+ (-length) + 0.5);
+ float gazeRollY =
+ (float)((Math.sin(-nGazeYaw/180.0*Math.PI) *
+ Math.sin(-face.getRollDirection()/
+ 180.0*Math.PI)-
+ Math.sin(nGazePitch/180.0*Math.PI) *
+ Math.cos(nGazeYaw/180.0*Math.PI) *
+ Math.cos(-face.getRollDirection()/
+ 180.0*Math.PI)) *
+ (-length) + 0.5);
+
+ if (face.getLeftEyeBlinkDegree() < blink_threshold) {
+ point[0] = face.leftEye.x;
+ point[1] = face.leftEye.y;
+ point[2] = face.leftEye.x + gazeRollX;
+ point[3] = face.leftEye.y + gazeRollY;
+ mMatrix.mapPoints (point);
+ canvas.drawLine(point[0] +dx, point[1] + dy,
+ point[2] + dx, point[3] +dy, mPaint);
+ }
+
+ if (face.getRightEyeBlinkDegree() < blink_threshold) {
+ point[0] = face.rightEye.x;
+ point[1] = face.rightEye.y;
+ point[2] = face.rightEye.x + gazeRollX;
+ point[3] = face.rightEye.y + gazeRollY;
+ mMatrix.mapPoints (point);
+ canvas.drawLine(point[0] + dx, point[1] + dy,
+ point[2] + dx, point[3] + dy, mPaint);
+ }
+ }
+
+ if (face.mouth != null) {
+ Log.e(TAG, "smile: " + face.getSmileDegree() + "," +
+ face.getSmileScore());
+ if (face.getSmileDegree() < smile_threashold_no_smile) {
+ point[0] = face.mouth.x + dx;
+ point[1] = face.mouth.y-delta_y +dy;
+ point[2] = face.mouth.x + dx;
+ point[3] = face.mouth.y+delta_y + dy;
+ mMatrix.mapPoints (point);
+ canvas.drawLine(point[0] + dx, point[1] + dy,
+ point[2] + dx, point[3] + dy, mPaint);
+
+ } else if (face.getSmileDegree() <
+ smile_threashold_small_smile) {
+
+ mRect.set(face.mouth.x-delta_x,
+ face.mouth.y-delta_y, face.mouth.x+delta_x,
+ face.mouth.y+delta_y);
+ mMatrix.mapRect(mRect);
+ mRect.offset(dx, dy);
+ canvas.drawArc(mRect, 0, 180, true, mPaint);
+ } else {
+ mRect.set(face.mouth.x-delta_x,
+ face.mouth.y-delta_y, face.mouth.x+delta_x,
+ face.mouth.y+delta_y);
+ mMatrix.mapRect(mRect);
+ mRect.offset(dx, dy);
+ canvas.drawOval(mRect, mPaint);
+ }
+ }
+ }
}
canvas.restore();
}