人脸切剪
对人脸进行一个截切
package cn.guoke.demo02;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import java.io.File;
import java.io.IOException;
public class Test_02 {
private static final String OPENCV_DLL_PATH = "D:\\java\\opencv\\opencv\\build\\java\\x64\\opencv_java3412.dll";
private static final String OPENCV_XML_PATH = "D:\\java\\opencv\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml";
public static void main(String[] args) throws IOException {
String[] strings = detectFaceImage("D:/b8d93909da582e6b47baa0de28e12337.jpg", "D:");
for (String string : strings) {
System.out.println(string);
}
}
/**
* @param imageFilePath 待处理图片路径
* @param destDir 提前人脸后居中裁剪后的图片存储目录
* @return 居中裁剪的图片路径
*/
private static String[] detectFaceImage(String imageFilePath, String destDir) {
File dir = new File(destDir);
// 1.引入opencv 库 Window引入dll 绝对路径
System.load(OPENCV_DLL_PATH);
// 2.引入训练好的XML格式的分类器文件
CascadeClassifier faceDetector = new CascadeClassifier(OPENCV_XML_PATH);
if (faceDetector.empty()) {
return null;
}
// 3.读取待处理的图片
File imgFile = new File(imageFilePath);
Mat image = Imgcodecs.imread(imgFile.getPath());
int srcWidth = image.width();
int srcHeight = image.height();
// 4.进行人脸检测
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(image, faceDetections);
Rect[] rectFace = faceDetections.toArray();
String[] targetFiles = new String[rectFace.length];
// 5.裁剪检测到的人脸图片
for (int i = 0; i < rectFace.length; i++) {
Rect rect = rectFace[i];
// 计算居中裁剪框
Rect centerCropBox = estimateCenterCropBox(srcWidth, srcHeight, rect);
// 裁剪框
targetFiles[i] = destDir + File.separator + i + getImageType(imgFile);
// 裁剪
cutCenterImage(imgFile.getPath(), targetFiles[i], centerCropBox);
}
return targetFiles;
}
/**
* @param imageFilePath 待处理图片路径
* @param destDir 提前人脸后居中裁剪后的图片存储目录
* @return 居中裁剪的图片路径
*/
private static String[] detectEysImage(String imageFilePath, String destDir) {
File dir = new File(destDir);
// 1.引入opencv 库 Window引入dll 绝对路径
System.load(OPENCV_DLL_PATH);
// 2.引入训练好的XML格式的分类器文件
CascadeClassifier faceDetector = new CascadeClassifier(OPENCV_XML_PATH);
if (faceDetector.empty()) {
return null;
}
// 3.读取待处理的图片
File imgFile = new File(imageFilePath);
Mat image = Imgcodecs.imread(imgFile.getPath());
int srcWidth = image.width();
int srcHeight = image.height();
// 4.进行人脸检测
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(image, faceDetections);
Rect[] rectFace = faceDetections.toArray();
String[] targetFiles = new String[rectFace.length];
// 5.裁剪检测到的人脸图片
for (int i = 0; i < rectFace.length; i++) {
Rect rect = rectFace[i];
// 计算居中裁剪框
Rect centerCropBox = estimateCenterCropBox(srcWidth, srcHeight, rect);
// 裁剪框
targetFiles[i] = destDir + File.separator + i + getImageType(imgFile);
// 裁剪
cutCenterImage(imgFile.getPath(), targetFiles[i], centerCropBox);
}
return targetFiles;
}
/**
* 获取文件后缀不带.
*
* @param file 文件后缀名
* @return
*/
private static String getImageType(File file) {
if (file != null && file.exists() && file.isFile()) {
String fileName = file.getName();
int index = fileName.lastIndexOf(".");
if (index != -1 && index < fileName.length() - 1) {
return fileName.substring(index);
}
}
return null;
}
/**
* 计算居中裁剪框
* 在原图边界范围内,以检测的人脸框为中心,向四周等比例放大,最大的裁剪框可保证人脸居中
*
* @param srcWidth 原始图像宽度
* @param srcHeight 原始图像高度
* @param rect 人脸框位置
* @return 居中裁剪框
*/
public static Rect estimateCenterCropBox(int srcWidth, int srcHeight, Rect rect) {
int w0 = rect.x;
int w1 = srcWidth - rect.x - rect.width;
int w2 = (srcHeight - rect.y - rect.height) * rect.width / rect.height;
int w3 = rect.width * rect.y / rect.height;
if (w0 < 0 || w1 < 0 || w2 < 0 || w3 < 0) {
return null;
}
int ret = w0;
if (ret > w1) {
ret = w1;
}
if (ret > w2) {
ret = w2;
}
if (ret > w3) {
ret = w3;
}
return new Rect(rect.x - ret, rect.y - ret * rect.height / rect.width,
rect.width + 2 * ret, rect.height + 2 * ret * rect.height / rect.width);
}
/**
* @param oriImg 原始图像
* @param outFile 裁剪的图像输出路径
* @param rect 剪辑矩形区域
*/
private static void cutCenterImage(String oriImg, String outFile, Rect rect) {
System.out.println("cutCenterImage ...");
// 原始图像
Mat image = Imgcodecs.imread(oriImg);
// Mat sub = new Mat(image,rect);
Mat sub = image.submat(rect);
Mat mat = new Mat();
Size size = new Size(rect.width, rect.height);
// 将人脸进行截图
Imgproc.resize(sub, mat, size);
// 截图保存到outFile
Imgcodecs.imwrite(outFile, mat);
}
}
截切前 :
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1hQRMGlE-1611189564938)(img\b8d93909da582e6b47baa0de28e12337.jpg)]
剪切后:
脸进行截图
Imgproc.resize(sub, mat, size);
// 截图保存到outFile
Imgcodecs.imwrite(outFile, mat);
}
}
``
截切前 :
这里图片上传不了 bug
剪切后: