[Android] 相机镜头前添加人脸提示框

需求

我们之前做了一款拍照APP,现在需要在拍摄的时候,提供一个人脸提示框(因为我们最后不是保留所有的图像,而是仅保留中间一部分图像)

思路

在预览图层前,再添加一层画布,在新的画布上绘制人脸框和矩形框。也就是说,实际上我们仅仅是在预览的镜头前添加,而非对相机做什么修改。

具体步骤

步骤一:添加新图层

使用FrameLayout(下方的内容会覆盖在上方的内容上),在我们的预览用SurfaceView之上添加一个自定义画布

<FrameLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <SurfaceView
        android:id="@+id/cameraSV"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="visible" />
    
    <com.example.matting.SVDraw
         android:id="@+id/drawIV"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent" />
</FrameLayout>

步骤二:自定义画布设置

public class SVDraw extends SurfaceView implements Callback{
    protected SurfaceHolder sh;
    private String TestTag = "TestLog";
    
    public SVDraw(Context context, AttributeSet attrs) {
        super(context, attrs);
        
        sh = getHolder();
        sh.addCallback(this);
        sh.setFormat(PixelFormat.TRANSPARENT); // 设置透明
        setZOrderOnTop(true); // 置顶
    }

    /*
    ...其他的一些函数
    */

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        
    }
}

步骤三:在画布上绘制矩形框及人脸框

使用函数的形式,方便外部调用

public synchronized void drawRect() {
    Canvas canvas = sh.lockCanvas();
    canvas.drawColor(Color.TRANSPARENT);

    // 红色提示矩形框画笔设置
    Paint redPaint = new Paint();
    redPaint.setAntiAlias(true);
    redPaint.setColor(Color.RED);
    redPaint.setStyle(Style.STROKE);
    redPaint.setStrokeWidth(4f);
    redPaint.setAlpha(100);
    
    // 绿色人物提示框画笔设置
    Paint greenPaint = new Paint();
    greenPaint.setAntiAlias(true);
    greenPaint.setColor(0xFFA4C739);
    greenPaint.setStrokeWidth(3.5f);
    greenPaint.setStyle(Paint.Style.STROKE);

    // 将画布原点移至画布中央(方便画布选点)
    canvas.translate(mWidth / 2, mHeight / 2 - 200);

    // 绘制外围红色边框
    canvas.drawRect(new Rect(-360, -480, 360, 480), redPaint);

    // 头部
    RectF rectf_head = new RectF(-225, -375, 225, 15);
    canvas.drawArc(rectf_head, 200, 140, false, greenPaint);

    // 下颌
    RectF rectf_mouse = new RectF(-165, 120, 165, 322);
    canvas.drawArc(rectf_mouse, 20, 140, false, greenPaint);


    // 衬衣
    canvas.drawLine(-141, 315, -300, 458, greenPaint);
    canvas.drawLine(141, 315, 300, 458, greenPaint);

    sh.unlockCanvasAndPost(canvas);
}

分为两部分,一部分红色画笔,绘制的是最终的裁剪区域外轮廓。一部分是分步的人脸绘制。也许可以采用贴图的方法整体实现,但是由于我没有半透明的矢量图可用,所以用蠢方法实现了。

步骤四:清屏函数

由于我们的人脸框是可以随时收回的,所以要添加一个函数,用于将绘制的图案隐藏,实际上我们是将绘制的图案直接清除,以此实现取消辅助线

void clearDraw() {
    Canvas canvas = sh.lockCanvas();
    canvas.drawColor(Color.BLUE);
    sh.unlockCanvasAndPost(canvas);
}

步骤五:声明属性

private SVDraw myDraw = null;

步骤六:onCreate中初始化第二层屏幕

// 初始化画板
myDraw = (SVDraw) findViewById(R.id.drawIV);

步骤七:添加函数调用

当需要添加辅助线的时候(比如说点击了添加按钮),调用相应的函数即可

myDraw.drawRect();

效果展示

提示框效果展示

灰色区域是预览区域,点击绘制后会显示红色提示框和绿色人脸框

完整代码

完整代码请移步github项目Github项目:《Matting》 By ZaoZhe6666
在camera.xml中是相机的相关布局。
在SVDraw.java中是本文提到的设置画布的绘制部分。
在UseCameraActivity中是本文对画布绘制功能(辅助线添加功能)的具体使用。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容