opencv.js进行图像边缘化检测与描边内存溢出?

新手上路,请多包涵

opencv.js进行图像边缘化检测与描边内存溢出
以下为我的代码,主要使用了递归调用,也在调用完成后删除掉了初始化的mat对象之类的。但是依然内存溢出。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Video Object Detection</title>
</head>
<body>
<video id="video" width="1280" height="720" autoplay></video>
<canvas id="canvas" width="1280" height="720"></canvas>
<script async src="../archives/js/opencv.js" onload="onOpenCvReady();"></script>
<script>
    let video = document.getElementById('video');
    let canvasElement = document.getElementById('canvas');
    let ctx = canvasElement.getContext('2d');

    let gray;
    let denoised;
    let edges;
    let fst;
    let hierarchy;
    let approx;
    let dst;
    let dst1;
    let kernel;
    let fsk;
    let sss;

    function onOpenCvReady() {
        navigator.mediaDevices.getUserMedia({video: {width: 1280, height: 720}})
            .then(stream => {
                video.srcObject = stream;
                video.play();  // 开始播放视频
            })
            .catch(err => {
                console.error("Error accessing media devices.", err);
            });

        // 监听 'play' 事件,确保视频开始播放后再进行检测和绘制
        video.addEventListener('play', detectAndDraw);
    }

    function detectAndDraw() {
       // console.log("开始");
        init();
        // 确保视频正在播放
        if (video.paused || video.ended) return;

        // 绘制视频帧到 canvas 上
        ctx.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);

        // 获取 canvas 上的图像数据并转换为 OpenCV 的 Mat 对象
        let src = cv.matFromImageData(ctx.getImageData(0, 0, canvasElement.width, canvasElement.height));

        // 图像处理:转换为灰度图
        cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY); // 重用 gray 对象

        // 降噪处理
        cv.bilateralFilter(gray, denoised, 9, 75, 75); // 重用 denoised 对象

        // 高斯滤波
        cv.GaussianBlur(denoised, denoised, new cv.Size(5, 5), 0, 0); // 使用降噪后的图像

        // 提取边缘
        cv.Canny(denoised, edges, 75, 150); // 重用 edges 对象

        // 膨胀
        cv.dilate(edges, edges, kernel); // 重用 kernel 和 edges 对象

        // 进行腐蚀操作
        cv.erode(edges, fst, fsk); // 重用 fst 和 fsk 对象

        // 提取外轮廓
        let contours = new cv.MatVector();
        cv.findContours(edges, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE);

        let index = 0, maxArea = 0, aindex = 0;
        const area = src.cols * src.rows;

        for (let i = 0; i < contours.size(); ++i) {
            let tempArea = Math.abs(cv.contourArea(contours.get(i)));
            if (tempArea > maxArea) {
                index = i;
                maxArea = tempArea;
            }
            if (tempArea > area * 0.03) {
                //console.log("底图面积:" + area + ";文件面积:" + tempArea);
                aindex++;
            }
        }

        if (maxArea > 0) {
            const foundContour = contours.get(index);
            const arcL = cv.arcLength(foundContour, true);
            cv.approxPolyDP(foundContour, approx, 0.02 * arcL, true); // 重用 approx 对象

            if (approx.total() === 4) {
                let points = [];
                const data32S = approx.data32S;
                for (let i = 0, len = data32S.length / 2; i < len; i++) {
                    points[i] = {x: data32S[i * 2], y: data32S[i * 2 + 1]};
                }
                //console.log("检测到四边形点:", points);

                let srcPoints = getSortedVertex(points).flatMap(p => [p.x, p.y]);

                // 在源图像上绘制绿色边框
                for (let i = 0; i < 4; i++) {
                    const startX = srcPoints[i * 2];
                    const startY = srcPoints[i * 2 + 1];
                    const endX = srcPoints[((i + 1) % 4) * 2];
                    const endY = srcPoints[((i + 1) % 4) * 2 + 1];

                    // 绘制线段,颜色为绿色,线宽为2
                    cv.line(src, new cv.Point(startX, startY), new cv.Point(endX, endY), new cv.Scalar(0, 255, 0, 255), 10);
                }
                cv.imshow(canvasElement, src);


                gray.delete();
                denoised.delete();
                edges.delete();
                fst.delete();
                hierarchy.delete();
                approx.delete();
                dst.delete();
                dst1.delete();
                kernel.delete();
                fsk.delete();
                contours.delete();

            }
        }

        requestAnimationFrame(detectAndDraw);
    }


    // 开始处理
    video.addEventListener('play', () => {
        detectAndDraw();
    });

    function getSortedVertex(points) {
        // 计算中心点
        const center = {
            x: points.reduce((sum, p) => sum + p.x, 0) / points.length,
            y: points.reduce((sum, p) => sum + p.y, 0) / points.length
        };

        // 计算每个点到中心点的角度
        const angles = points.map(p => {
            return {
                point: p,
                angle: Math.atan2(p.y - center.y, p.x - center.x) * 180 / Math.PI
            };
        });

        // 按角度排序
        const sortedPoints = angles.sort((a, b) => a.angle - b.angle).map(a => a.point);
        return sortedPoints;
    }


    function init() {
        //console.log("初始化");
        sss = 1;
        gray = new cv.Mat();
        denoised = new cv.Mat();
        edges = new cv.Mat();
        fst = new cv.Mat();
        hierarchy = new cv.Mat();
        approx = new cv.Mat();
        dst = new cv.Mat();
        dst1 = new cv.Mat();
        kernel = cv.getStructuringElement(cv.MORPH_RECT, new cv.Size(7, 7));
        fsk = cv.getStructuringElement(cv.MORPH_RECT, new cv.Size(5, 5));
    }
</script>
</body>
</html>

处理掉内存溢出的问题

阅读 720
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏