需求:任意自拍照,生成证件照,有特定的检测接口
这里提供一点基础,人脸识别脸部区域,最大坐标借用了face++的抠图判断透明度获取,https://console.faceplusplus.com.cn/documents/40608240
public class TestOpencv {
static {
// 载入opencv的库
/*String opencvpath = TestOpencv2.class.getResource("/opencv").getPath() + "/";
String opencvDllName = opencvpath + Core.NATIVE_LIBRARY_NAME + ".dll";
System.out.println(opencvDllName);
System.load(opencvDllName);*/
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}
private static final int orgWidth = 354;
private static final int orgHeight = 472;
/**
* 将BufferedImage类型转换成Mat类型
*
* @param bfImg
* @param imgType bufferedImage的类型 如 BufferedImage.TYPE_3BYTE_BGR
* @param matType 转换成mat的type 如 CvType.CV_8UC3
* @return
*/
public static Mat bufferedImage2Mat(BufferedImage bfImg, int imgType, int matType) {
BufferedImage original = bfImg;
int itype = imgType;
int mtype = matType;
if (original == null) {
throw new IllegalArgumentException("original == null");
}
if (original.getType() != itype) {
BufferedImage image = new BufferedImage(original.getWidth(), original.getHeight(), itype);
Graphics2D g = image.createGraphics();
try {
g.setComposite(AlphaComposite.Src);
g.drawImage(original, 0, 0, null);
} finally {
g.dispose();
}
}
byte[] pixels = ((DataBufferByte) original.getRaster().getDataBuffer()).getData();
Mat mat = Mat.eye(original.getHeight(), original.getWidth(), mtype);
mat.put(0, 0, pixels);
return mat;
}
public static BufferedImage mat2BufferedImage(Mat matrix) throws IOException {
MatOfByte mob = new MatOfByte();
Imgcodecs.imencode(".jpg", matrix, mob);
return ImageIO.read(new ByteArrayInputStream(mob.toArray()));
}
/**
* opencv实现人脸识别
*
* @param bufferedImage
* @throws Exception
*/
public static Map<String, Integer> detectFace(BufferedImage bufferedImage) throws Exception {
System.out.println("Running DetectFace ... ");
// 从配置文件lbpcascade_frontalface.xml中创建一个人脸识别器,该文件位于opencv安装目录中
CascadeClassifier faceDetector = new CascadeClassifier(
TestOpencv2.class.getResource("/opencv").getPath() + "/" + "haarcascade_frontalface_alt.xml");
//Mat image = Imgcodecs.imread(imagePath);
Mat image = bufferedImage2Mat(bufferedImage, BufferedImage.TYPE_3BYTE_BGR, CvType.CV_8UC3);
if (image.width() < orgWidth || image.height() < orgHeight) {
throw new RuntimeException("人脸图像尺寸必须不小于" + orgWidth + "*" + orgHeight);
}
// 在图片中检测人脸
MatOfRect faceDetections = new MatOfRect();
//参数设置为scaleFactor=1.1f, minNeighbors=4, flags=0 以此来增加识别人脸的正确率
//人脸识别的最大和最小像素范围minSize和maxSize
faceDetector.detectMultiScale(image, faceDetections, 1.1f, 4, 0, new Size(120, 120));
System.out.println(String.format("Detected %s faces", faceDetections.toArray().length));
Rect[] rects = faceDetections.toArray();
if (0 == rects.length) {
throw new RuntimeException("人脸图像必须不小于120*120,无法识别人脸图像");
}
if (rects.length > 1) {
throw new RuntimeException("超过一个脸");
}
// 在每一个识别出来的人脸周围画出一个方框
Rect rect = rects[0];
Imgproc.rectangle(image, new Point(rect.x, rect.y),
new Point(rect.x + rect.width, rect.y + rect.height),
new Scalar(0, 255, 0));
//Imgcodecs.imwrite(outFile, image);
//System.out.println(String.format("人脸识别成功,人脸图片文件为: %s", outFile));
Map<String, Integer> map = new HashMap<>();
map.put("x", rect.x);
map.put("y", rect.y);
map.put("w", rect.width);
map.put("h", rect.height);
map.put("width", image.width());
map.put("height", image.height());
return map;
}
/**
* 裁剪图片并重新装换大小
*
* @param bufferedImage
* @param posX
* @param posY
* @param width
* @param height
*/
public static BufferedImage imageCut(BufferedImage bufferedImage, int posX, int posY, int width, int height) throws IOException {
//原始图像
Mat image = bufferedImage2Mat(bufferedImage, BufferedImage.TYPE_3BYTE_BGR, CvType.CV_8UC3);//Imgcodecs.imread(imagePath);
//截取的区域:参数,坐标X,坐标Y,截图宽度,截图长度
Rect rect = new Rect(posX, posY, width, height);
//两句效果一样
Mat sub = image.submat(rect); //Mat sub = new Mat(image,rect);
Mat mat = new Mat();
Size size = new Size(width, height);
Imgproc.resize(sub, mat, size,1);//将人脸进行截图并保存
return mat2BufferedImage(mat);
//Imgcodecs.imwrite(outFile, mat);
//System.out.println(String.format("图片裁切成功,裁切后图片文件为: %s", outFile));
}
public static void main(String[] args) throws Exception {
String picNo = "2";
BufferedImage buffImage1 = ImageIO.read(new FileInputStream("C:\\Users\\GC\\Desktop\\z" + picNo + ".jpg"));
System.out.println("buffImage1:" + buffImage1.getWidth());
//handleDpi(buffImage1,300,300);
Map<String, Integer> map = detectFace(buffImage1);
int rectX = map.get("x");
int rectY = map.get("y");
int rectWidth = map.get("w");
int rectHeight = map.get("h");
int oldWidht = map.get("width");
int oldHeight = map.get("height");
System.out.println(map);
ImageIO.write(buffImage1, "jpg", new File("C:\\Users\\GC\\Desktop\\g"+picNo+".jpg"));
System.exit(0);
}
}