10分钟学会用 opencv.js 实现人脸识别

1,111 阅读2分钟

OpenCV 是一个基于 Apache2.0 许可(开源)发行的跨平台计算机视觉和机器学习软件库。

准备

首先我们要下载 opencv.js,这里使用的版本是 3.4.14

官网没有直接提供下载地址,这里我们可以从使用文档里下载

opencv.js

还有一个utils.js也要下载

utils.js

人脸识别模型文件

haarcascade_frontalface_default.xml

image.png

然后新建一个index.html

  1. 展示一张图片
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>人脸识别</title>
  </head>
  <body>
    <div>
      <input type="file" id="file" />

      <p><canvas id="dist" /></p>
    </div>

    <script src="opencv.js"></script>
    <script src="utils.js"></script>

    <script>
      const fileElement = document.getElementById("file");

      fileElement.addEventListener("change", (e) => {
        const img = new Image();
        img.onload = function () {
          // 读取图片
          let src = cv.imread(img);
          // 展示图片
          cv.imshow("dist", src);
          // 释放
          src.delete();
        };
        img.src = URL.createObjectURL(e.target.files[0]);
      });
    </script>
  </body>
</html>
  1. 在图片上画一个矩形
<script>
  const fileElement = document.getElementById("file");

  fileElement.addEventListener("change", (e) => {
    const img = new Image();
    img.onload = function () {
      // 读取图片
      let src = cv.imread(img);

      let point1 = new cv.Point(img.width * 0.1, img.height * 0.1);
      let point2 = new cv.Point(img.width * 0.9, img.height * 0.9);
      cv.rectangle(src, point1, point2, [255, 0, 0, 255]);

      // 展示图片
      cv.imshow("dist", src);
      // 释放
      src.delete();
    };
    img.src = URL.createObjectURL(e.target.files[0]);
  });
</script>    

image.png

  1. 人脸检测
<script>
  // 这里需要使用utils异步下载模型
  let utils = new Utils();
  // 模型的路径
  let faceCascadeFile = "haarcascade_frontalface_default.xml";
  utils.createFileFromUrl(faceCascadeFile, faceCascadeFile, () => {
    const fileElement = document.getElementById("file");

    fileElement.addEventListener("change", (e) => {
      const img = new Image();
      img.onload = function () {
        // 读取图片
        let src = cv.imread(img);

        // 创建用于目标检测的级联分类器
        let faceCascade = new cv.CascadeClassifier();
        // 读取模型
        faceCascade.load(faceCascadeFile);
        // 矩形向量,用于存放检测到的对象
        let faces = new cv.RectVector();
        // 对象检测。检测到的对象以矩形列表的形式返回。
        faceCascade.detectMultiScale(src, faces);
        // 一张图中可能存在多个人脸
        for (let i = 0; i < faces.size(); ++i) {
          // 矩形左上角坐标
          let point1 = new cv.Point(faces.get(i).x, faces.get(i).y);
          // 矩形右下角坐标
          let point2 = new cv.Point(faces.get(i).x + faces.get(i).width, faces.get(i).y + faces.get(i).height);
          // 用红色标出人脸矩形框
          cv.rectangle(src, point1, point2, [255, 0, 0, 255]);
        }
        // 展示图片
        cv.imshow("dist", src);
        // 释放资源
        src.delete();
        faceCascade.delete();
        faces.delete();
      };
      img.src = URL.createObjectURL(e.target.files[0]);
    });
  });
</script>

这里发现有识别错误的地方,可以尝试调整faceCascade.detectMultiScale的参数

参数说明
imageCV_8U类型的矩阵,包含检测到对象的图像。
objects矩形向量,其中每个矩形包含检测到的对象,矩形可能部分在原始图像之外。
scaleFactor指定图像大小在每个图像比例下缩小多少的参数。
minNeighbors参数,指定每个候选矩形应该有多少个neighbors来保留它。
flags参数,与函数cvHaarDetectObjects中旧级联的含义相同。它不用于新的级联。
minSize可能的最小对象大小。小于该值的对象将被忽略。
maxSize可能的最大对象大小。大于该值的对象将被忽略。如果maxSize == minSize模型将在固定尺度上进行检测。

尝试把scaleFactor调整为1.2,faceCascade.detectMultiScale(src, faces, 1.2)