我想使用FaceDetector播放服务在Android中捕获具有不同面部滤镜的图像。
FaceDetector未在Face中显示正确的过滤器设置。图像:
Research in different projects in GitHub 1 2 3 但没有得到最佳解决方案。
示例项目代码:
MainActivity.java
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Environment;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.widget.ImageView;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.Frame;
import com.google.android.gms.vision.face.Face;
import com.google.android.gms.vision.face.FaceDetector;
import java.io.File;
import java.io.FileOutputStream;
public class MainActivity extends AppCompatActivity {
ImageView imageView;
private void init() {
imageView = (ImageView) findViewById(R.id.img);
}
Bitmap b;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
final FaceDetector detector = new FaceDetector.Builder(getApplicationContext())
.setTrackingEnabled(false)
.setMode(FaceDetector.FAST_MODE)
.setLandmarkType(FaceDetector.NO_LANDMARKS)
.setClassificationType(FaceDetector.NO_CLASSIFICATIONS)
.build();
Runnable r = new Runnable() {
@Override
public void run() {
imageView.buildDrawingCache();
b = imageView.getDrawingCache();
Frame frame = new Frame.Builder().setBitmap(b).build();
imageView.getDrawingCache(false);
Detector<Face> safeDetector = new SafeFaceDetector(detector);
Log.d("PRI", "Detector started");
SparseArray<Face> faceSparseArray = detector.detect(frame);
Log.d("PRI", "Detector complete");
Log.d("PRI", String.valueOf(faceSparseArray.size()));
if (!safeDetector.isOperational()) {
// Note: The first time that an app using face API is installed on a device, GMS will
// download a native library to the device in order to do detection. Usually this
// completes before the app is run for the first time. But if that download has not yet
// completed, then the above call will not detect any faces.
//
// isOperational() can be used to check if the required native library is currently
// available. The detector will automatically become operational once the library
// download completes on device.
// Check for low storage. If there is low storage, the native library will not be
// downloaded, so detection will not become operational.
IntentFilter lowstorageFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW);
boolean hasLowStorage = registerReceiver(null, lowstorageFilter) != null;
if (hasLowStorage) {
//Toast.makeText(this, R.string.low_storage_error, Toast.LENGTH_LONG).show();
}
} else {
createImage(b, faceSparseArray);
}
detector.release();
}
};
new Handler().postDelayed(r, 500);
}
private void createImage(Bitmap b, SparseArray<Face> faceSparseArray) {
Log.d("PRI", "Create Image Started");
Bitmap bmOverlay = Bitmap.createBitmap(b.getWidth(), b.getHeight(), b.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(b, new Matrix(), null);
Log.d("PRI", String.valueOf(faceSparseArray.size()));
for (int i = 0; i < faceSparseArray.size(); i++) {
Face face = faceSparseArray.valueAt(i);
Log.d("PRI1", String.valueOf(face));
Bitmap b2 = BitmapFactory.decodeResource(getResources(), R.drawable.mask4);
Bitmap b3 = Bitmap.createScaledBitmap(b2, (int) face.getWidth(),
(int) ((b2.getHeight() * face.getWidth()) / b2.getWidth()), false);
float x = face.getPosition().x + face.getWidth() / 2;
float y = face.getPosition().y + face.getHeight() / 2;
float xOffset = face.getWidth() / 2.0f;
float yOffset = face.getHeight() / 2.0f;
canvas.drawBitmap(b3, x - xOffset, y - yOffset, new Paint());
Log.d("PRI", "Create Image Complete");
}
imageView.setImageBitmap(bmOverlay);
try {
// Use the compress method on the Bitmap object to write image to
// the OutputStream
File f = new File(Environment.getExternalStorageDirectory() + "/tempImage.png");
if (!f.canWrite())
f.setWritable(true);
FileOutputStream fos = new FileOutputStream(f);
// Writing the bitmap to the output stream
bmOverlay.compress(Bitmap.CompressFormat.PNG, 2, fos);
fos.close();
Log.e("saveToInternalStorage()", "DONE");
} catch (Exception e) {
Log.e("saveToInternalStorage()", e.getMessage());
}
}
}
MainActivity.xml
<RelativeLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="face_camera.lyrebirdstudio.com.facedefaultimage.MainActivity">
<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/data" />
</RelativeLayout>