OpenCV在Android上实现人脸背景虚化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wblgers1234/article/details/77842469

1. 背景

在手机拍照技术日新月异的今天,很多手机厂商都陆续上了双摄,并衍生出人像模式(背景虚化)。虽然博主不是很懂双摄虚化的原理,但是看到一些样张之后,还是被深深吸引,觉得很漂亮,很有虚幻的感觉。
小米6的人像模式&背景虚化

自己也想动手做一个“图像虚化”的Demo来玩玩,当然并不是用的手机的双摄原理,而是用一些图像处理的算法。比如说高斯模糊,博主阮一峰的这篇博客对“高斯模糊在图像处理中的应用”讲得非常详细,大家可以移步去看看,我这里就不再赘述。

http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html

简而言之,高斯模糊就是对每一个像素点的值,以二维高斯分布的概率作为权重,对周围”kernal”范围的像素点的值做像素加权得到新的像素值。

2. 虚化背景提取

我们要做背景虚化,首先需要先把拍照的目标或者重心提取出来,其余的称为背景。在上一篇《OpenCV实战:Android Studio配置并运行OpenCV4Android的face-detection》的博客里,我们基于OpenCV4Android的sample完成了人脸检测功能。

那么基于此,我们可以按照下列的步骤做虚化背景提取:

  • 利用人脸检测的矩形框得到一系列轮廓点MatOfPoint;
  • 创建一个灰度值为0的单通道Mat图像hole,并在hole上面画出上一步得到的轮廓;
  • 对原始的检测到人脸的图像mRgba进行高斯模糊处理,得到frameBlur;
  • 将原始图像mRgba中的轮廓内部分利用mask的方式拷贝进frameBlur
  • 最终得到的图像frameBlur就是对人脸背景虚化处理的图像。

    主要的算法代码如下:

Mat hole = new Mat(rows, cols, CvType.CV_8UC1, new Scalar(0));
Imgproc.drawContours(hole, last_contour, last_contour.size()-1, new Scalar(255),-1);

Mat frameBlur = new Mat(rows, cols, mRgba.type());
Imgproc.GaussianBlur(mRgba, frameBlur, new Size(61, 61), 0);
mRgba.copyTo(frameBlur, hole);//将原图像拷贝进遮罩图层

mImageView.setImageBitmap(matToBitmap(frameBlur));

3. 其余的关键代码

3.1 Layout

整个Android工程的layout配置如下,可以看到除了用来显示camera预览图像的activity_main之外,还加入了cameraImageView,它是用来显示虚化后的静态图像,即我们这个工程的虚化处理不是实时的。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <org.opencv.android.JavaCameraView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/activity_main" />

    <ImageView android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/cameraImageView"/>

</RelativeLayout>

3.2 OnTouchListener

对于主程序class MainActivity,添加了对OnTouchListener的实现来支持触摸事件,当用户触摸屏幕的任何一点时,完成拍照功能,并对当前图像进行虚化处理。关键代码在于需要重新实现OnTouchListener的函数onTouch来处理监听事件。

public boolean onTouch(View v, MotionEvent event) {

    cameraView_OnTouch(v, event);
    isImageViewShown = true;
    return false;
}


private void cameraView_OnTouch(View view, MotionEvent event) {

    //
    //虚化背景提取
    //

    mImageView.setImageBitmap(matToBitmap(frameBlur));
    // show imageView and hide cameraView
    mOpenCvCameraView.setVisibility(View.INVISIBLE);
    mImageView.setVisibility(View.VISIBLE);
}

当onTouch触发时,mOpenCvCameraView会被隐藏,同时mImageView被显示,完成camera预览视频与静态图片的切换。

4. 测试结果

原始图片:
这里写图片描述

手机上的实测虚化效果:
这里写图片描述

看起来还是不错的哦!

5. 代码下载

本工程的全部代码我都上传到github和CSDN,请在下面的地址进行下载,用Android Studio打开,配置就可以运行:
Github:
https://github.com/wblgers/OpenCV_Android_Plus/tree/master/OpenCVFaceBlur

CSDN:
http://download.csdn.net/download/wblgers1234/9965755

猜你喜欢

转载自blog.csdn.net/wblgers1234/article/details/77842469
今日推荐