如何在firebase mlkit中正确对齐面部轮廓?
Posted
技术标签:
【中文标题】如何在firebase mlkit中正确对齐面部轮廓?【英文标题】:how to align face contour properly in firebase mlkit? 【发布时间】:2019-05-18 15:25:19 【问题描述】:我看到了很多例子,并尝试创建一个面部轮廓应用程序,一切都按预期工作,但无论出于何种原因,这些点都没有与实际面部对齐。
这是我的活动代码
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.otaliastudios.cameraview.CameraView
android:id="@+id/cvv"
android:layout_
android:layout_
app:cameraFacing="front"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" >
<com.kirtu.simpletexts.texts.OverlayView
android:id="@+id/overlayView"
android:layout_
android:layout_
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true" />
</com.otaliastudios.cameraview.CameraView>
</android.support.constraint.ConstraintLayout>
这里是主要的活动代码
public class filter extends AppCompatActivity
int previewh,previeww;
CameraView cv;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.filter);
cv = findViewById(R.id.cvv);
cv.setLifecycleOwner(this);
cv.start();
final OverlayView ov = findViewById(R.id.overlayView);
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
FirebaseVisionFaceDetectorOptions op =new FirebaseVisionFaceDetectorOptions.Builder()
.setContourMode(FirebaseVisionFaceDetectorOptions.ALL_CONTOURS)
.build();
final FirebaseVisionFaceDetector detector= FirebaseVision.getInstance().getVisionFaceDetector(op);
cv.addFrameProcessor(new FrameProcessor()
@Override
public void process(@NonNull Frame frame)
if(frame.getSize() != null)
int rotation = frame.getRotation()/ 90;
if(rotation/2 == 0)
previewh = cv.getPreviewSize().getHeight();
previeww = cv.getPreviewSize().getWidth();
//Log.d("texts", "process: "+cv.getPreviewSize().getWidth()+" "+cv.getPreviewSize().getHeight());
else
previewh = cv.getPreviewSize().getWidth();
previeww = cv.getPreviewSize().getHeight();
//Log.d("texts", "process: "+cv.getPreviewSize().getWidth()+" "+cv.getPreviewSize().getHeight());
FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
.setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
.setWidth(frame.getSize().getWidth())
.setHeight(frame.getSize().getHeight())
.setRotation(rotation)
.build();
FirebaseVisionImage fvi = FirebaseVisionImage.fromByteArray(frame.getData(),metadata);
final FirebaseVisionFace[] fc = new FirebaseVisionFace[1];
detector.detectInImage(fvi).addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionFace>>()
@Override
public void onSuccess(List<FirebaseVisionFace> firebaseVisionFaces)
for(FirebaseVisionFace f : firebaseVisionFaces)
ov.previewh = previewh;
ov.previeww = previeww;
ov.face = f;
ov.invalidate();
).addOnFailureListener(new OnFailureListener()
@Override
public void onFailure(@NonNull Exception e)
);
);
@Override
protected void onResume()
super.onResume();
cv.start();
@Override
protected void onPause()
super.onPause();
cv.stop();
@Override
protected void onDestroy()
super.onDestroy();
cv.destroy();
这是覆盖代码
public class OverlayView extends View
public int previewh;
public int previeww;
public FirebaseVisionFace face;
public Rect rect;
private float widthScaleFactor = 1.0f;
private float heightScaleFactor = 1.0f;
Context c;
Bitmap draw = BitmapFactory.decodeResource(getResources(),R.drawable.pimg);
public OverlayView(Context context, AttributeSet attr)
super(context,attr);
this.c = context;
this.postInvalidate();
@Override
protected void onDraw(Canvas canvas)
super.onDraw(canvas);
if(face!= null && canvas != null && previewh != 0 && previeww != 0)
widthScaleFactor = getWidth()/previeww;
heightScaleFactor = getHeight()/previewh;
float maxx = 0;
float minx = 10000;
float maxy = 0;
float miny = 10000;
List<FirebaseVisionPoint> facce3= face.getContour(FirebaseVisionFaceContour.ALL_POINTS).getPoints();
for(FirebaseVisionPoint f : facce3)
Paint p1 = new Paint();
p1.setStyle(Paint.Style.FILL);
p1.setColor(Color.GREEN);
p1.setStrokeWidth(5);
canvas.drawPoint(translateX(f.getX()+50),translateY(f.getY()+50),p1);
maxx = translateX(maxx);
minx = translateX(minx);
maxy = translateY(maxy);
miny = translateY(miny);
//Log.d("texts", "onDraw: "+maxx+" "+minx+" "+maxy+" "+miny);
Rect r1 = new Rect(Math.round(maxx),Math.round(miny),Math.round(minx),Math.round(maxy));
private float translateX(Float x)
return getWidth()-scaleX(x);
private float scaleX(Float x)
return x*widthScaleFactor;
private float translateY(Float x)
Resources resources = c.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
return (scaleY(x)+resources.getDimensionPixelSize(resourceId));
private float scaleY(Float x) return x*heightScaleFactor;
我尝试通过添加一些值来调整 X 和 Y 值,但结果发现其中一侧没有被点覆盖
可以做些什么来使它在所有方面都正确对齐。
【问题讨论】:
您是否为分析仪设置了分辨率和纵横比? 【参考方案1】:您可以在官方 firebase/quickstart-android 的repository 上查看GraphicOverlay.java:
/**
* Adjusts the x coordinate from the preview's coordinate system to the view coordinate system.
*/
public float translateX(float x)
if (overlay.facing == CameraSource.CAMERA_FACING_FRONT)
return overlay.getWidth() - scaleX(x);
else
return scaleX(x);
/**
* Adjusts the y coordinate from the preview's coordinate system to the view coordinate system.
*/
public float translateY(float y)
return scaleY(y);
另外,人脸识别官方文档:Detect Faces with MK Kit on Android。
【讨论】:
以上是关于如何在firebase mlkit中正确对齐面部轮廓?的主要内容,如果未能解决你的问题,请参考以下文章
MLKit 旋转面部图像使其笔直(iOS 和 Android)
MLKit Firebase android - 如何将 FirebaseVisionFace 转换为图像对象(如位图)?