1、核心工具类

public static List<FaceSuccessInfo> faceChage(Mat mat,String fileUrl) {
		List<FaceSuccessInfo> list = new ArrayList<FaceSuccessInfo>();
		List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
		ImageInfo imageInfo = ImageFactory.bufferedImage2GrayImageInfo(Mat2BufImg(mat,".png"));
		//人脸检测
		int errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(),imageInfo.getImageFormat(), faceInfoList);
		if(faceInfoList.size() <= 0)
			return null;
		//特征提取2
		FaceFeature faceFeature = new FaceFeature();
		//循环遍历识别到的人脸
		for (int i = 0; i<faceInfoList.size(); i++) {
			errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(i), faceFeature);
			FaceFeature targetFaceFeature = new FaceFeature();
			targetFaceFeature.setFeatureData(faceFeature.getFeatureData());
			boolean faceIs = false;
			//得到复制好了的常量变量
			for (int j = 0; j < FaceDB.facedb.size(); j++) {
				FaceSimilar faceSimilar = new FaceSimilar();
				errorCode = faceEngine.compareFaceFeature(targetFaceFeature, FaceDB.facedb.get(j).getFaceFeature(), faceSimilar);
				//小数变百分比
				int number = Integer.parseInt(new DecimalFormat("0").format(faceSimilar.getScore()*100));
				if(number > FACE_SIMILARITY) {
					faceIs = true;
					//绘制方框
					/*Imgproc.rectangle(mat,
							new Point(faceInfoList.get(i).getRect().getLeft(),faceInfoList.get(i).getRect().getTop()),
							new Point(faceInfoList.get(i).getRect().getRight(),faceInfoList.get(i).getRect().getBottom()),
							contrastColor, 2);*/
					//人脸图不能大于背景图
					int x = faceInfoList.get(i).getRect().getLeft();
					if(x < 0)
						x = x * -1;
					int y = faceInfoList.get(i).getRect().getTop();
					if(y < 0)
						y = y * -1;
					int width = faceInfoList.get(i).getRect().getRight() - faceInfoList.get(i).getRect().getLeft();
					if(width < 0)
						width = width * -1;
					int height = faceInfoList.get(i).getRect().getBottom() - faceInfoList.get(i).getRect().getTop();
					if(height < 0)
						height = height * -1;

					//判断截图不能超过图片大小
					if(mat.cols()<(x+width))
						width = mat.cols() - x;
					if(mat.rows() <(y+height))
						height = mat.rows() - y;

					//读取头
					Mat srcImageMat = Imgcodecs.imread(fileUrl);
					Mat msk1 = Imgcodecs.imread(fileUrl,0);
					Mat msk = msk1.clone();
					//反色
					Core.bitwise_not(msk1,msk);

					Mat newSrcImageMat = new Mat();
					Imgproc.resize(srcImageMat, newSrcImageMat, new Size(width, height));
					Mat newMsk = new Mat();
					Imgproc.resize(msk, newMsk, new Size(width, height));
					//感兴趣的区域
					Mat imageROI = new Mat(mat,new Rect(x, y, width, height));

					newSrcImageMat.copyTo(imageROI,newMsk);
					//newSrcImageMat.copyTo(imageROI);
					//System.out.println("mat1 = " + newMsk.channels());
					//System.out.println("mat = " + mat.channels());

					//添加返回数据
					FaceSuccessInfo fsi = new FaceSuccessInfo();
					fsi.setFaceId(FaceDB.facedb.get(j).getFaceId());
					fsi.setFaceSimilarity(number);
					fsi.setName(FaceDB.facedb.get(j).getName());
					list.add(fsi);
					break;
				}
			}
		}
		return list;
	}

开发过程中,中间有个反色的操作卡了我很久,我一直以为是RGB三通道而RGBA是四通道,通道引起的PNG不透明。改了通道还是不透明,最后把图像通道分离了再和并还是白色。还好在看C++的一篇文章的时候来了灵感。

int main(){ 
    Mat image = imread("1.jpg"); 
    Mat logo = imread("2.png"); 
    Mat mask = imread("2.png",0); //注意要是灰度图才行 
    threshold(mask,mask,254,255,CV_THRESH_BINARY); 
    Mat mask1 = 255 - mask; //掩模反色 
    //imshow("img",mask1); 
    Mat imageROI; 
    imageROI = image(Rect(480,320,logo.cols,logo.rows)); 
    logo.copyTo(imageROI,mask1); 
    namedWindow("result"); 
    imshow("result",image); 
    imwrite("result.jpg",image); 
    waitKey(); 
    return 0; 
}

掩模反色 ,在java中是

//反色
Core.bitwise_not(msk1,msk);

2、最后再来看看初步的实现效果吧

人脸贴合的算法后面还要改,现在只是一个Demo,不过用来做鬼畜视频效果够了,哈哈。

3、视频

原视频

换脸后

 

最后修改于 2021-01-27 22:03:09
如果觉得我的文章对你有用,请随意赞赏
扫一扫支付
上一篇