spring boot基于opencv实现人脸识别


前言

最近公司项目有个新需求,需要对小程序拍摄的照片进行人脸识别,并且将人脸部分截取保存到服务器,用于人脸结果分析,网上查了很多资料,敲定了使用opencv做人脸识别,项目是spring boot,下面会具体细说

一、OpenCV简介

OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。 它轻量级而且高效–由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

二、安装opencv

这个是opencv的中文文档

参考地址: http://www.woshicver.com/

1.下载opencv

这里我是在windows安装的(我安装的是4.5.1版本):

参考地址:https://blog.csdn.net/LEON1741/article/details/90211061

2.配置

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文件所在目录

在这里插入图片描述

在这里插入图片描述

三、测试

1.代码

@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();
      }
  }

2.效果

在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值