我正在尝试使用facedetection进行Face swap应用程序。直到现在我得到位图中检测到的面孔并在检测到的面上绘制椭圆形。但现在我需要使用椭圆内的面,以便我可以交换两个面。可能吗。我需要一些关于此的建议。
我的活动课程如下
public class FaceDetectionActivity extends Activity
{
public MyView faceview;
public ImageView gallery;
private Uri imageURI;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
setContentView(R.layout.main);
faceview = (MyView)findViewById(R.id.faceview);
gallery=(ImageView)findViewById(R.id.gallery);
gallery.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, 0 );
}
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if(requestCode==0){
imageURI = data.getData();
try {
Bitmap b = android.provider.MediaStore.Images.Media.getBitmap(getContentResolver(), imageURI);
faceview.myBitmap=b;
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
faceview.invalidate();
}
faceview.invalidate();
} else {
System.exit(0);
Log.e("result", "BAD");
}
}
}
和我的观点类
public class MyView extends ImageViewTouchBase {
public RectF rectF;
public Bitmap myBitmap;
private int width, height;
private FaceDetector.Face[] detectedFaces;
private int NUMBER_OF_FACES=10;
private FaceDetector faceDetector;
private int NUMBER_OF_FACE_DETECTED;
private float eyeDistance;
Matrix mImageMatrix;
public MyView(Context context, AttributeSet attrs)
{
super(context, attrs);
BitmapFactory.Options bitmapFatoryOptions=new BitmapFactory.Options();
bitmapFatoryOptions.inPreferredConfig=Bitmap.Config.RGB_565;
myBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.familyportrait,bitmapFatoryOptions);
width=myBitmap.getWidth();
height=myBitmap.getHeight();
detectedFaces=new FaceDetector.Face[NUMBER_OF_FACES];
faceDetector=new FaceDetector(width,height,NUMBER_OF_FACES);
NUMBER_OF_FACE_DETECTED=faceDetector.findFaces(myBitmap, detectedFaces);
}
@Override
protected void onDraw(Canvas canvas)
{
if(myBitmap!=null)
{
canvas.drawBitmap(myBitmap, 0,0, null);
}
Paint myPaint = new Paint();
myPaint.setColor(Color.GREEN);
myPaint.setStyle(Paint.Style.STROKE);
myPaint.setStrokeWidth(3);
for(int count=0;count<NUMBER_OF_FACE_DETECTED;count++)
{
Face face=detectedFaces[count];
PointF midPoint=new PointF();
face.getMidPoint(midPoint);
eyeDistance=face.eyesDistance();
float left = midPoint.x - (float)(1.4 * eyeDistance);
float right = midPoint.x + (float)(1.4 * eyeDistance);
float top = midPoint.y - (float)(1.8 * eyeDistance);
float bottom = midPoint.y + (float)(1.8 * eyeDistance);
Rect imageRect = new Rect(0, 0, width, height);
rectF = new RectF();
rectF.set(left,top,right,bottom);
canvas.drawOval(rectF, myPaint);
}
}
}
现在我想要选择椭圆内的内容。请给我一些想法。
答案 0 :(得分:2)
我只是想通了。我正在创建另一个位图,其中包含上述代码中的变量Left,Right,Top和Bottom。然后我得到了face的正方形位图。我从方形位图面提取圆形位图。多数民众赞成。
答案 1 :(得分:0)
尝试以下代码:
公共类MainActivity扩展了ProgressA {
public static final String FACE_1 = "face_1";
public static final String FACE_2 = "face_2";
private ImageView mIvForDetect;
private ImageView mIvForDetect2;
private ImageView mIvForDetect3;
private ImageView mIvForDetect4;
//private Bitmap baseBTM;
private Bitmap face1BTM;
private Bitmap face2BTM;
boolean face1Done = false;
boolean face2Done = false;
private FirebaseVisionFaceDetector detector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mIvForDetect = findViewById(R.id.iv_main_for_detect);
mIvForDetect2 = findViewById(R.id.iv_main_for_detect2);
mIvForDetect3 = findViewById(R.id.iv_main_for_detect3);
mIvForDetect4 = findViewById(R.id.iv_main_for_detect4);
//baseBTM = BitmapFactory.decodeResource(getResources(), R.drawable.paj);
mIvForDetect.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.jolie));
mIvForDetect2.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.pitt));
detector = FirebaseVision.getInstance().getVisionFaceDetector(buildCloudVisionOptions());
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showProgressDialog();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
detectFace(mIvForDetect, FACE_1, null);
detectFace(mIvForDetect2,FACE_2, null);
}
});
thread.start();
}
});
}
private void checkFaces() {
if (face1Done && face2Done){
swapFaces();
}
}
private void swapFaces() {
detectFace(mIvForDetect, FACE_1, face2BTM);
detectFace(mIvForDetect2, FACE_2, face1BTM);
}
private void detectFace(final ImageView view, final String face, final Bitmap fakeFace) {
final Bitmap baseBTM = ((BitmapDrawable) view.getDrawable()).getBitmap();
FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(baseBTM);
detector.detectInImage(image)
.addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionFace>>() {
@Override
public void onSuccess(List<FirebaseVisionFace> faces) {
if (fakeFace != null){
setFakeFace(view, faces.get(0), baseBTM, fakeFace);
hideProgressDialog();
}else {
switch (face){
case FACE_1:
face1BTM = createTrimmedBitmap(cutFaces(faces.get(0), baseBTM));
mIvForDetect3.setImageBitmap(face1BTM);
face1Done = true;
checkFaces();
break;
case FACE_2:
face2BTM = createTrimmedBitmap(cutFaces(faces.get(0), baseBTM));
mIvForDetect4.setImageBitmap(face2BTM);
face2Done = true;
checkFaces();
break;
}
}
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
hideProgressDialog();
Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
public FirebaseVisionFaceDetectorOptions buildCloudVisionOptions() {
return new FirebaseVisionFaceDetectorOptions.Builder()
.setPerformanceMode(FirebaseVisionFaceDetectorOptions.ACCURATE)
.setLandmarkMode(FirebaseVisionFaceDetectorOptions.ALL_LANDMARKS)
.setClassificationMode(FirebaseVisionFaceDetectorOptions.ALL_CLASSIFICATIONS)
.setPerformanceMode(FirebaseVisionFaceDetectorOptions.FAST)
.build();
}
public static Bitmap createTrimmedBitmap(Bitmap bmp) {
int imgHeight = bmp.getHeight();
int imgWidth = bmp.getWidth();
int smallX = 0, largeX = imgWidth, smallY = 0, largeY = imgHeight;
int left = imgWidth, right = imgWidth, top = imgHeight, bottom = imgHeight;
for (int i = 0; i < imgWidth; i++) {
for (int j = 0; j < imgHeight; j++) {
if (bmp.getPixel(i, j) != Color.TRANSPARENT) {
if ((i - smallX) < left) {
left = (i - smallX);
}
if ((largeX - i) < right) {
right = (largeX - i);
}
if ((j - smallY) < top) {
top = (j - smallY);
}
if ((largeY - j) < bottom) {
bottom = (largeY - j);
}
}
}
}
bmp = Bitmap.createBitmap(bmp, left, top, imgWidth - left - right, imgHeight - top - bottom);
return bmp;
}
public Bitmap cutFaces(FirebaseVisionFace face, Bitmap baseBTM) {
Bitmap tempBitmap = Bitmap.createBitmap(baseBTM.getWidth(), baseBTM.getHeight(), Bitmap.Config.RGB_565);
Canvas tempCanvas = new Canvas(tempBitmap);
tempCanvas.drawBitmap(baseBTM, 0, 0, null);
int top = face.getBoundingBox().top;
int left = Math.round(face.getLandmark(FirebaseVisionFaceLandmark.LEFT_EAR).getPosition().getX());
int right = Math.round(face.getLandmark(FirebaseVisionFaceLandmark.RIGHT_EAR).getPosition().getX());
int bottom = face.getBoundingBox().bottom;
Bitmap output = Bitmap.createBitmap(tempBitmap.getWidth(), tempBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
canvas.drawOval(left, top, right, bottom, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(tempBitmap, new Matrix(), paint);
return output;
}
public void setFakeFace(ImageView view, FirebaseVisionFace face, Bitmap baseBTM, Bitmap fakeFace) {
Bitmap resultBitmap = Bitmap.createBitmap(baseBTM.getWidth(), baseBTM.getHeight(), baseBTM.getConfig());
Canvas canvas = new Canvas(resultBitmap);
final Paint paintSRC = new Paint();
final Paint paintDST = new Paint();
int top = face.getBoundingBox().top;
int left = Math.round(face.getLandmark(FirebaseVisionFaceLandmark.LEFT_EAR).getPosition().getX());
int right = Math.round(face.getLandmark(FirebaseVisionFaceLandmark.RIGHT_EAR).getPosition().getX());
int bottom = face.getBoundingBox().bottom;
int weight = right - left;
int height = bottom - top;
canvas.drawOval(left, top, right, bottom, paintSRC);
paintSRC.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
paintDST.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
Matrix matrix = new Matrix();
matrix.postScale(face.getLandmark(FirebaseVisionFaceLandmark.LEFT_EAR).getPosition().getX(), face.getBoundingBox().top);
canvas.drawBitmap(baseBTM, 0, 0, null);
canvas.drawBitmap(Bitmap.createScaledBitmap(fakeFace, weight, height, false), left, top, paintDST);
view.setImageBitmap(resultBitmap);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}