使用 Java 实现人脸融合!

知道的越多,不知道的就越多,业余的像一棵小草!

编辑:业余草
来源:https://www.xttblog.com/?p=5019

B站:业余草

人脸融合正在流行,毕竟这个社会一直都是看脸的时代!

今天周六,抽个时间给大家闲聊一下人脸融合技术。

说到这个技术,很多人可能很陌生,但是当提到 AI 人脸识别,AI 换脸,AI 算命,人脸美化等技术,相信都不陌生了。

况且这个技术目前 BAT 等巨头都有涉猎,国内的人工智能巨头新秀也不例外。可以说谁先占领了 AI,谁就在下一代浪潮中立身于不败之地。

说回技术本身,我也只是略懂皮毛。下面说一下,具体的实现思路。

如上图所示,在图片上的人脸中,找出这些特征点(一般,找 68、72 个就可以了)。

如果脸型相同或相近,那么就可以换脸,进行融合了。

说起来简单,但是实现起来就涉及到很多算法了。

目前市面上多数的 APP 都是借助 Face++,BAT 等提供的 sdk api 实现的。这方面的 API 调用费用还挺贵的!

我的实现也很简单,借助开源类库,加上巨头提供的 API,基于 Java 实现人脸融合。

首先,利用 opencv 获得关键特征点。

public static void main(String[] args) throws FileNotFoundException {
    String path1 = ResourceUtils.getFile("classpath:img/3m.jpg").getAbsolutePath();
    String path2 = ResourceUtils.getFile("classpath:img/2m.jpg").getAbsolutePath();
    String savePath = "/User/业余草/face";//图片存放位置
    // 参数说明
    // type :opencv和baidu 两种获取人脸标记的位置点
    // true 使用全部点位进行分割,false使用外部轮廓的点位进行融合
    OpenCVFaceSwap.faceMerge(path1,path2,savePath,"opencv",true);
}

然后,进行第三方 API 调用。

//人脸检测
ImageInfo imageInfo = getRGBData(path1);
List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
System.out.println(faceInfoList);
//特征提取
FaceFeature faceFeature = new FaceFeature();
errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
System.out.println("特征值大小:" + faceFeature.getFeatureData().length);
//人脸检测2
ImageInfo imageInfo2 = getRGBData(path2);
List<FaceInfo> faceInfoList2 = new ArrayList<FaceInfo>();
errorCode = faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(),imageInfo.getImageFormat(), faceInfoList2);
System.out.println(faceInfoList);
//特征提取2
FaceFeature faceFeature2 = new FaceFeature();
errorCode = faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo.getImageFormat(), faceInfoList2.get(0), faceFeature2);
System.out.println("特征值大小:" + faceFeature.getFeatureData().length);
//特征比对
FaceFeature targetFaceFeature = new FaceFeature();
targetFaceFeature.setFeatureData(faceFeature.getFeatureData());
FaceFeature sourceFaceFeature = new FaceFeature();
sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData());
FaceSimilar faceSimilar = new FaceSimilar();
errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
System.out.println("相似度:" + faceSimilar.getScore());
//引擎卸载
errorCode = faceEngine.unInit();

上面就是比较核心的代码。

public static Mat flow(Mat mat) {
        // 灰度
        mat = OpencvUtil.gray(mat); 
        // 二值化 此处绝定图片的清晰度
        mat = OpencvUtil.binary(mat);  
        // 腐蚀  去除背景图片
        mat = OpencvUtil.erode(mat, 1);   
        return mat;
}
/**
 * 灰化处理
 *
 * @return
 */
public static Mat gray(Mat mat) {
        Mat gray = new Mat();
        opencv_imgproc.cvtColor(mat, gray, opencv_imgproc.COLOR_BGR2GRAY, 1);
        return gray;
}
/**
 * 增强对比
 * @param mat
 * @return
 */
public static Mat splitBGR(Mat mat) { 
        MatVector splitBGR = new MatVector();
        opencv_core.split(mat, splitBGR);
        for (int i = 0; i<mat.channels(); i++){
                opencv_imgproc.equalizeHist(splitBGR.get(i), splitBGR.get(i));
        }  
        opencv_core.merge(splitBGR, mat);  
        return mat;
}

另外还涉及到一些图片的特殊处理,利用的也是 Opencv。

说白了,我不具有核心技术,我就是一个 API 调用工程师。核心算法我一概不懂,专业造轮子。

做的牛逼一点的,可以从视频中提取图片,再进行融合。

感兴趣的,可以尝试自己查查资料,借助各云服务厂商的免费 API 调用额度,做一款让自己“吃到饱”的应用!

本文中的源码,只是一个简单的 demo,有兴趣的可以加我 WX:codedq,拿去接着研究研究!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章