OpenCV.js报错cv未定义:图像转二进制功能异常排查
问题排查:OpenCV.js 中 cv 未定义错误
问题现象
实现图像转二进制功能,设置两个Canvas分别显示原始图像和二值化图像。原始图像显示功能正常,但添加二值化代码后控制台报错:
script.js:26 Uncaught ReferenceError: cv is not defined
at file:///***script.js:26:11
原始HTML代码
<p id="status">OpenCV.js is loading...</p> <div> <div class="inputoutput"> <img id="imageSrc" alt="No Image" /> <div class="caption">imageSrc <input type="file" id="fileInput" name="file" /></div> </div> <div class="inputoutput"> <canvas id="canvasOutput" ></canvas> <div class="caption">canvasOutput</div> </div> <div class="inputoutput"> <canvas id="canvasBinary"></canvas> <div class="caption">Binary</div> </div> </div> <script type="text/javascript" src="scriptOCV.js"> </script> <script async src="opencv.js" type="text/javascript"></script>
原始JavaScript代码
let imgElement = document.getElementById('imageSrc'); let inputElement = document.getElementById('fileInput'); inputElement.addEventListener('change', (e) => { imgElement.src = URL.createObjectURL(e.target.files[0]); }, false); //read image imgElement.onload = function () { let mat = cv.imread(imgElement); cv.imshow('canvasOutput', mat); mat.delete(); }; //check openCV var Module = { onRuntimeInitialized() { document.getElementById('status').innerHTML = 'OpenCV.js is ready.'; } }; //convert img -> binary let src = cv.imread('canvasOutput'); let dst = new cv.Mat(); cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0); cv.adaptiveThreshold(src, dst, 200, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 3, 2); cv.imshow('canvasBinary', dst); src.delete(); dst.delete();
问题根源
- 异步加载时序问题:OpenCV.js 通过
async属性加载,属于异步资源,会在页面其他同步脚本执行完毕后才完成加载。你的二值化代码直接写在全局作用域,会在OpenCV.js还未初始化完成时就执行,此时cv对象尚未定义,触发报错。 - 偶发性正常的假象:原图显示的代码(
imgElement.onload内的cv调用)看似正常,是因为用户选择文件并加载图片的过程耗时较长,大概率此时OpenCV.js已经加载完成,但这是偶然情况,并非可靠的写法。
修复方案
将所有依赖cv对象的逻辑(包括图像加载、显示、二值化)全部放到Module.onRuntimeInitialized回调函数内,确保只有当OpenCV.js完全加载就绪后才执行这些代码。同时,调整图像加载逻辑,确保每次用户选择新图片时都能重新生成二值图。
修复后的JavaScript代码
var Module = { onRuntimeInitialized() { document.getElementById('status').innerHTML = 'OpenCV.js is ready.'; let imgElement = document.getElementById('imageSrc'); let inputElement = document.getElementById('fileInput'); // 处理文件选择事件 inputElement.addEventListener('change', (e) => { imgElement.src = URL.createObjectURL(e.target.files[0]); }, false); // 图像加载完成后执行显示与二值化 imgElement.onload = function () { // 显示原始图像到canvasOutput let mat = cv.imread(imgElement); cv.imshow('canvasOutput', mat); // 执行二值化处理 let src = mat.clone(); let dst = new cv.Mat(); cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0); cv.adaptiveThreshold(src, dst, 200, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 3, 2); cv.imshow('canvasBinary', dst); // 释放内存 mat.delete(); src.delete(); dst.delete(); }; } };
额外注意事项
- OpenCV.js的
Mat对象占用内存,使用后务必调用delete()方法释放,避免内存泄漏。 - 确保
Module对象的定义在opencv.js加载脚本之前,这样OpenCV.js才能正确绑定到这个自定义的Module配置上。
内容的提问来源于stack exchange,提问作者Riszky hermawan
相关产品推荐
相关产品推荐

