基于边缘保留滤波实现人脸磨皮的算法

简介: 基于边缘保留滤波实现人脸磨皮的算法

快速边缘保留滤波



快速边缘保留滤波是通过积分图像实现局部均方差的边缘保留模糊算法,计算简单而且可以做到计算量跟半径无关。


首先局部均方差滤波中计算局部均值的公式如下:

image.png

计算局部均值.png


当边缘很弱的时候系数K趋近于0、该点的矫正之后的像素值就接近平均值。而当边缘很强的时候系数K趋近于1、该点的模糊之后的像素值就接近等于输入像素值。上述计算中最中意的是窗口内像素的均值与方差,计算均值可以根据积分图像很容易得到,而计算方差根据一系列的数学推导可以得到如下的结果


image.png

推导结果.png


算法实现的步骤:



1. 快速边缘保留滤波


核心的算法如下:

@Override
    public ImageProcessor filter(ImageProcessor src) {
        // initialization parameters
        int width = src.getWidth();
        int height = src.getHeight();
        xr = yr = (int)(Math.max(width, height) * 0.02);
        sigma = 10 + sigma * sigma * 5;
        // start ep process
        byte[] output = new byte[width*height];
        IntIntegralImage ii = new IntIntegralImage();
        for(int i=0; i<src.getChannels(); i++) {
            System.arraycopy(src.toByte(i), 0, output, 0, output.length);
            ii.setImage(src.toByte(i));
            ii.process(width, height, true);
            processSingleChannel(width, height, ii, output);
            System.arraycopy(output, 0, src.toByte(i), 0, output.length);
        }
        // release memory
        output = null;
        return src;
    }
    public void processSingleChannel(int width, int height, IntIntegralImage input, byte[] output) {
        float sigma2 = sigma*sigma;
        int offset = 0;
        int wy = (yr * 2 + 1);
        int wx = (xr * 2 + 1);
        int size = wx * wy;
        int r = 0;
        for (int row = yr; row < height-yr; row++) {
            offset = row * width;
            for (int col = xr; col < width-xr; col++) {
                int sr = input.getBlockSum(col, row, wy, wx);
                float a = input.getBlockSquareSum(col, row, wy, wx);
                float b = sr / size;
                float c = (a - (sr*sr)/size)/size;
                float d = c / (c+sigma2);
                r = (int)((1-d)*b + d*r);
                output[offset + col] = (byte)Tools.clamp(r);
            }
        }
    }


其中,IntIntegralImage封装了积分图像的算法,具体可以查看 cv4j 中的实现。


2. 皮肤检测


基于RGB颜色空间的简单阈值肤色识别来实现皮肤检测,算法如下:


R>95 And G>40 And B>20 And R>G And R>B And Max(R,G,B)-Min(R,G,B)>15 And Abs(R-G)>15

public class DefaultSkinDetection implements ISkinDetection{
// RGB Color model pixel skin detection method
// (R, G, B) is classified as skin if:
// R > 95 and G > 40 and B > 20 and
// max(R, G, B) - min(R, G, B) > 15 and
// |R-G| > 15 and R > G and R > B
//===============================================
    @Override
    public boolean findSkin(int tr, int tg, int tb) {
        return isSkin(tr, tg, tb);
    }
    @Override
    public boolean isSkin(int tr, int tg, int tb) {
        int max = Math.max(tr, Math.max(tg, tb));
        int min = Math.min(tr, Math.min(tg, tb));
        int rg = Math.abs(tr - tg);
        if(tr > 95 && tg > 40 && tb > 20 && rg > 15 && 
                (max - min) > 15 && tr > tg && tr > tb) {
            return true;
        } else {
            return false;
        }
    }
}


3. 梯度滤波


梯度滤波器也叫高通滤波器。梯度滤波器有好几种不同方式,在这里用的是Sobel。


Sobel算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息,边缘定位精度不够高。当对精度要求不是很高时,是一种较为常用的边缘检测方法。由于Sobel算法简单效率高,所以我们在这里选择它。


4. BeautySkinFilter


结合以上三步,在 cv4j 中实现人脸磨皮的滤镜BeautySkinFilter

package com.cv4j.core.filters;
import com.cv4j.core.datamodel.ByteProcessor;
import com.cv4j.core.datamodel.ImageProcessor;
/**
 * Created by gloomy fish on 2017/4/23.
 */
public class BeautySkinFilter implements CommonFilter {
    @Override
    public ImageProcessor filter(ImageProcessor src) {
        int width = src.getWidth();
        int height = src.getHeight();
        byte[] R = new byte[width*height];
        byte[] G = new byte[width*height];
        byte[] B = new byte[width*height];
        System.arraycopy(src.toByte(0), 0, R, 0, R.length);
        System.arraycopy(src.toByte(1), 0, G, 0, G.length);
        System.arraycopy(src.toByte(2), 0, B, 0, B.length);
        FastEPFilter epFilter = new FastEPFilter();
        epFilter.filter(src);
        ISkinDetection skinDetector = new DefaultSkinDetection();
        int r = 0, g = 0, b = 0;
        for(int i=0; i<R.length; i++) {
            r = R[i]&0xff;
            g = G[i]&0xff;
            b = B[i]&0xff;
            if(!skinDetector.isSkin(r, g, b)) {
                src.toByte(0)[i] = (byte)r;
                src.toByte(1)[i] = (byte)g;
                src.toByte(2)[i] = (byte)b;
            }
        }
        byte[] gray = new byte[width*height];
        int c = 0;
        for(int i=0; i<R.length; i++) {
            r = R[i] & 0xff;
            g = G[i] & 0xff;
            b = B[i] & 0xff;
            c = (int)(0.299 *r + 0.587*g + 0.114*b);
            gray[i] = (byte)c;
        }
        GradientFilter gradientFilter = new GradientFilter();
        int[] gradient = gradientFilter.gradient(new ByteProcessor(gray, width, height));
        gray = null;
        for(int i=0; i<R.length; i++) {
            r = R[i]&0xff;
            g = G[i]&0xff;
            b = B[i]&0xff;
            if(gradient[i] > 50) {
                src.toByte(0)[i] = (byte)r;
                src.toByte(1)[i] = (byte)g;
                src.toByte(2)[i] = (byte)b;
            }
        }
        return src;
    }
}


5. 最终效果


BeautySkinFilter跟原先的滤镜用法是一样的,一行代码就可以实现想要的效果:)

RxImageData.bitmap(bitmap).addFilter(new BeautySkinFilter()).into(image1);


来看看在 Android 上的最终效果:


image.png

人脸磨皮效果.png


总结:



cv4jgloomyfish和我一起开发的图像处理库,纯java实现,目前还处于早期的版本。这次的人脸磨皮算法也还有改进空间,未来我们还会继续优化该算法。

相关文章
|
6月前
|
算法
【MATLAB】语音信号识别与处理:滑动平均滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:滑动平均滤波算法去噪及谱相减算法呈现频谱
175 0
|
6月前
|
算法
【MATLAB】语音信号识别与处理:SG滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:SG滤波算法去噪及谱相减算法呈现频谱
232 1
|
6月前
|
算法
【MATLAB】语音信号识别与处理:T1小波滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:T1小波滤波算法去噪及谱相减算法呈现频谱
151 0
|
6月前
|
传感器 算法 计算机视觉
基于肤色模型和中值滤波的手部检测算法FPGA实现,包括tb测试文件和MATLAB辅助验证
该内容是关于一个基于肤色模型和中值滤波的手部检测算法的描述,包括算法的运行效果图和所使用的软件版本(matlab2022a, vivado2019.2)。算法分为肤色分割和中值滤波两步,其中肤色模型在YCbCr色彩空间定义,中值滤波用于去除噪声。提供了一段核心程序代码,用于处理图像数据并在FPGA上实现。最终,检测结果输出到&quot;hand.txt&quot;文件。
|
6月前
|
算法
【MATLAB】语音信号识别与处理:移动中位数滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:移动中位数滤波算法去噪及谱相减算法呈现频谱
88 2
|
6月前
|
算法
【MATLAB】语音信号识别与处理:卷积滑动平均滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:卷积滑动平均滤波算法去噪及谱相减算法呈现频谱
119 0
|
6月前
|
算法
【MATLAB】语音信号识别与处理:一维信号NLM非局部均值滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:一维信号NLM非局部均值滤波算法去噪及谱相减算法呈现频谱
135 1
|
6月前
|
算法
【MATLAB】语音信号识别与处理:高斯加权移动平均滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:高斯加权移动平均滤波算法去噪及谱相减算法呈现频谱
245 0
|
25天前
|
机器学习/深度学习 算法 数据处理
EM算法对人脸数据降维(机器学习作业06)
本文介绍了使用EM算法对人脸数据进行降维的机器学习作业。首先通过加载ORL人脸数据库,然后分别应用SVD_PCA、MLE_PCA及EM_PCA三种方法实现数据降维,并输出降维后的数据形状。此作业展示了不同PCA变种在人脸数据处理中的应用效果。
28 0
|
4月前
|
算法
基于kalman滤波的UAV三维轨迹跟踪算法matlab仿真
本文介绍了一种使用卡尔曼滤波(Kalman Filter)对无人飞行器(UAV)在三维空间中的运动轨迹进行预测和估计的方法。该方法通过状态预测和观测更新两个关键步骤,实时估计UAV的位置和速度,进而生成三维轨迹。在MATLAB 2022a环境下验证了算法的有效性(参见附图)。核心程序实现了状态估计和误差协方差矩阵的更新,并通过调整参数优化滤波效果。该算法有助于提高轨迹跟踪精度和稳定性,适用于多种应用场景,例如航拍和物流运输等领域。
201 12