使用 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,拿去接着研究研究!

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