java idea openCV 人脸照片裁剪
先上opencv 工具代码
package com.example.demo.util; import org.apache.commons.io.FileUtils; import org.opencv.core.*; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import org.opencv.objdetect.CascadeClassifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.MultipartConfigFactory; import org.springframework.context.annotation.Bean; import org.springframework.core.io.Resource; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.servlet.MultipartConfigElement; import javax.servlet.http.HttpServletResponse; import java.io.*; /** * @Author wong * @MethodName * @Description //TODO 人脸裁剪 * @Date 11:31 2021/3/16 **/ @RestController public class OpenCVController { @Value("classpath:haarcascade_frontalface_alt.xml") private Resource xml; @PostMapping("/face") public void FaceDetector(HttpServletResponse response,MultipartFile file) throws IOException { // D:\workspace-sts-3.9.2.RELEASE\OpenCV\src\main\resources // String opencvpath = System.getProperty("user.dir") + // "\\src\\main\\resources\\"; // String opencvDllName = opencvpath + Core.NATIVE_LIBRARY_NAME + ".dll"; // System.load(opencvDllName); System.loadLibrary(Core.NATIVE_LIBRARY_NAME); System.out.println("人脸检测开始……"); // 创建临时文件,因为boot打包后无法读取文件内的内容 File targetXmlFile = new File("src/" + xml.getFilename() + ""); FileUtils.copyInputStreamToFile(xml.getInputStream(), targetXmlFile); CascadeClassifier faceDetector = new CascadeClassifier(targetXmlFile.toString()); if (faceDetector.empty()) { System.out.println("请引入文件……"); return; } // 创建图片tempFile File tempFile = new File("src/" + file.getOriginalFilename() + ""); FileUtils.copyInputStreamToFile(file.getInputStream(), tempFile); // 读取创建的图片tempFile Mat image = Imgcodecs.imread(tempFile.toString()); MatOfRect faceDetections = new MatOfRect(); // 进行人脸检测 faceDetector.detectMultiScale(image, faceDetections); System.out.println(String.format("检测到人脸: %s", faceDetections.toArray().length)); Integer i = 1; // 制图将图填充到image中 for (Rect rect : faceDetections.toArray()) { Imgproc.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0), 3); imageCut(tempFile.toString(), i+".jpg", rect.x, rect.y, rect.width, rect.height);// 进行图片裁剪 i++; } // 下面部分是返回给页面 String filename = file.getOriginalFilename(); Imgcodecs.imwrite(filename, image); File imgFile = new File(filename); if (imgFile.exists()) { response.getOutputStream().write(toByteArray(imgFile)); response.getOutputStream().close(); } // 删除临时文件 if (targetXmlFile.exists() && targetXmlFile.isFile()) { if (targetXmlFile.delete()) { System.out.println("删除临时文件" + targetXmlFile + "成功!"); } } if (imgFile.exists() && imgFile.isFile()) { if (imgFile.delete()) { System.out.println("删除临时文件" + imgFile + "成功!"); } } if (tempFile.exists() && tempFile.isFile()) { if (tempFile.delete()) { System.out.println("删除临时文件" + tempFile + "成功!"); } } } public static void imageCut(String imagePath, String outFile, int posX, int posY, int width, int height) { // 原始图像 Mat image = 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);// 将人脸进行截图并保存 Imgcodecs.imwrite(outFile, mat); System.out.println(String.format("图片裁切成功,裁切后图片文件为: %s", outFile)); } public static byte[] toByteArray(File file) throws IOException { File f = file; if (!f.exists()) { throw new FileNotFoundException("file not exists"); } ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length()); BufferedInputStream in = null; try { in = new BufferedInputStream(new FileInputStream(f)); int buf_size = 1024; byte[] buffer = new byte[buf_size]; int len = 0; while (-1 != (len = in.read(buffer, 0, buf_size))) { bos.write(buffer, 0, len); } return bos.toByteArray(); } catch (IOException e) { e.printStackTrace(); throw e; } finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } bos.close(); } } // /** // * 设置文件上传大小 // * @return // */ // @Bean // public MultipartConfigElement multipartConfigElement() { // MultipartConfigFactory factory = new MultipartConfigFactory(); // //单个文件最大 // factory.setMaxFileSize(DataSize.ofMegabytes(5)); //MB // //factory.setMaxFileSize(DataSize.ofKilobytes(80)); //KB // //factory.setMaxFileSize(DataSize.ofGigabytes(80)); //Gb // /// 设置总上传数据总大小 // factory.setMaxRequestSize(DataSize.ofMegabytes(50)); // return factory.createMultipartConfig(); // } }
第一步: 下载opencv 的jar包 ,根据自己的环境下载,我的是Windows 环境的
https://opencv.org/releases/
下载完成后,点击 exe 安装 ,自己配置路径安装就好了
安装完毕后就可以导入jar包了 我这里是演示的是 idea
首先打开 项目配置管理
添加jar 包
找到自己安装opencv 文件夹里的java jar包 进行添加
添加后在列表会有显示
然后配置自己的vm启动路径
路径格式 : -Djava.library.path=D:\openCV\opencv\build\java\x64;D:\openCV\opencv\build\java\x64
这时候启动 会报错, 因为没有 haarcascade_frontalface_alt.xml文件
找到opencv 安装 路径下的这个文件就行了
粘贴到项目中
有些老铁还是报错, 那就看下target calsses包有这个文件没有,有时候是编译问题
直接 clean 再 build 下就行了
到这里就配置完成 接下来测试一下 debug启动项目 后 postman 进行测试
测试结果
看下裁剪后的照片 , 在本项目的根目录
有些会遇到图片文件 过大的问题
两种解决方法
第一种是 使用 bean 配置 MultipartFile 的文件大小
第二种是 在配置文件中配置
#配置文件传输 spring.servlet.multipart.enabled=true #单个数据的大小 spring.servlet.multipart.max-file-size=20MB #总数据的大小 spring.servlet.multipart.max-request-size=100MB