You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助解决OpenCV.js报错TypeError: cv.Mat is not a constructor

解决TypeError: cv.Mat is not a constructor 问题

我一眼就看出问题出在哪了——你的代码在OpenCV.js完全加载并初始化完成之前就尝试调用了cv对象的API,这就是为什么会抛出cv.Mat is not a constructor的错误。

问题根源分析

你的HTML里有两个关键问题:

  1. index.js和opencv.js都加了async属性,且index.js放在了opencv.js前面。浏览器异步加载脚本时,大概率会先执行index.js,这时候OpenCV还没加载完成,cv对象要么不存在,要么未完成初始化,自然找不到Mat构造函数。
  2. 你给opencv.js绑定了onload="onOpenCvReady();"事件,但代码里根本没定义这个函数,等于白绑定了,完全起不到等待OpenCV加载的作用。

解决方案步骤

1. 调整脚本加载逻辑

移除index.js的async属性,把它放到opencv.js后面,确保OpenCV先加载;同时在index.js里定义onOpenCvReady函数,让所有依赖OpenCV的代码都在这个函数里执行。

2. 修复代码里的遗漏问题

你的原代码里还缺少streaming变量定义,这会导致后续逻辑报错,需要补充;另外要注意videoInput是canvas元素,而cv.VideoCapture通常用于处理HTMLVideoElement,如果是处理摄像头流需要额外调整。

修改后的完整代码

Index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello OpenCV.js</title>
</head>
<body>
<h2>Hello OpenCV.js</h2>
<p id="status">OpenCV.js is loading...</p>
<div>
<img src="dd.jpg" style="display:none;" id ="img">
<canvas id = "videoInput" height="500" width="500"></canvas>
<canvas id = "canvasOutput" height="500" width="500"></canvas>
<!-- 先加载OpenCV,再加载业务代码,并绑定加载完成事件 -->
<script src="opencv.js" onload="onOpenCvReady();" type="text/javascript"></script>
<script type="text/javascript" src="index.js"></script>
</body>
</html>

index.js

// 定义OpenCV加载完成后的回调函数
function onOpenCvReady() {
  document.getElementById('status').innerHTML = 'OpenCV.js is ready.';
  
  let video = document.getElementById('videoInput');
  let src = new cv.Mat(video.height, video.width, cv.CV_8UC4);
  let dst = new cv.Mat(video.height, video.width, cv.CV_8UC4);
  let gray = new cv.Mat();
  let cap = new cv.VideoCapture(video);
  let faces = new cv.RectVector();
  let classifier = new cv.CascadeClassifier();
  // 加载预训练分类器,确保文件路径正确
  classifier.load('haarcascade_frontalface_default.xml');
  const FPS = 30;
  // 补充缺失的streaming变量,控制视频处理循环
  let streaming = true;

  function processVideo() {
    try {
      if (!streaming) {
        // 清理资源
        src.delete();
        dst.delete();
        gray.delete();
        faces.delete();
        classifier.delete();
        return;
      }
      let begin = Date.now();
      // 读取帧并处理
      cap.read(src);
      src.copyTo(dst);
      cv.cvtColor(dst, gray, cv.COLOR_RGBA2GRAY, 0);
      // 检测人脸
      classifier.detectMultiScale(gray, faces, 1.1, 3, 0);
      // 绘制人脸框
      for (let i = 0; i < faces.size(); ++i) {
        let face = faces.get(i);
        let point1 = new cv.Point(face.x, face.y);
        let point2 = new cv.Point(face.x + face.width, face.y + face.height);
        cv.rectangle(dst, point1, point2, [255, 0, 0, 255]);
      }
      cv.imshow('canvasOutput', dst);
      // 调度下一帧处理
      let delay = 1000/FPS - (Date.now() - begin);
      setTimeout(processVideo, delay);
    } catch (err) {
      console.error(err); // 替换原代码中未定义的utils.printError
    }
  };
  // 启动处理循环
  setTimeout(processVideo, 0);
}

额外注意事项

  • 确保haarcascade_frontalface_default.xml文件路径正确,和HTML文件在同一目录或路径配置无误。
  • 如果你是想处理摄像头视频流,需要将videoInput改为HTMLVideoElement,再通过navigator.mediaDevices.getUserMedia获取媒体流并绑定到video元素上。

内容的提问来源于stack exchange,提问作者Mohammad Ummair

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:26:08