使用 Java 实现人脸融合!

2020-06-08 09:49:00 浏览数 (2)

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

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

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

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

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

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

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

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

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

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

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

代码语言:javascript复制
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 调用。

代码语言:javascript复制
//人脸检测
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();

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

代码语言:javascript复制
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 调用工程师。核心算法我一概不懂,专业造轮子。

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

0 人点赞