赞
踩
最近公司项目有个新需求,需要对小程序拍摄的照片进行人脸识别,并且将人脸部分截取保存到服务器,用于人脸结果分析,网上查了很多资料,敲定了使用opencv做人脸识别,项目是spring boot,下面会具体细说
OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。 它轻量级而且高效–由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
这个是opencv的中文文档
这里我是在windows安装的(我安装的是4.5.1版本):
参考地址:https://blog.csdn.net/LEON1741/article/details/90211061
Eclipse
配置:
参考地址:https://blog.csdn.net/qq_37598011/article/details/86521560
idea
配置(我使用的idea)
1、下载完成后解压:
2、拷贝jar包和haarcascade_frontalface_alt.xml文件拷贝到项目resources目录下
3、修改pom文件
<dependency>
<groupId>org.opencv</groupId>
<artifactId>opencv</artifactId>
<version>4.5.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/opencv-451.jar</systemPath>
</dependency>
4、编辑springboot类的VM配置,指定opencv_java451.dll文件所在的目录
-Djava.library.path=dll文件所在目录
@PostMapping("/upload") public void FaceDetector(HttpServletResponse response, MultipartFile multipartFile) throws IOException { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); System.out.println("人脸检测开始……"); //对图片进行降采样 InputStream inputStream = multipartFile.getInputStream(); File tofile = IOUtil.mult2File(multipartFile); BufferedImage bufImg = ImageIO.read(inputStream); inputStream.close(); int w = bufImg.getWidth(); int h = bufImg.getHeight(); if (bufImg.getWidth()>1000||bufImg.getHeight()>1000){ w=bufImg.getWidth()/2; h=bufImg.getHeight()/2; } Thumbnails.of(multipartFile.getInputStream()).size(w, h).toFile(tofile); //图片到这就已经压缩好了,后面我全是为了上传到oss上做准备工作 InputStream inputStreams = new FileInputStream(tofile); MultipartFile file = new MockMultipartFile(tofile.getName(), inputStreams); // 创建临时文件,因为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/" + "121.jpg" + ""); 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-10), (rect.y-60)), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0), 4); imageCut(tempFile.toString(), i+".jpg", (rect.x-20), (rect.y-60), (rect.width + 30), (rect.height + 110));// 进行图片裁剪 i++; } // 下面部分是返回给页面 String filename = "111.jpg"; 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 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(); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。