如何在不将 canvas 附加到页面的情况下使用 canvas 从视频中解析图像数据?

How to use canvas for parsing imageData from video without appending canvas to the page?

我有 Webcam class,用于从网络摄像头捕获数据。 class 将数据流式传输到视频标签并将其绘制在 canvas 上,我还有 QRScanner class,用于解析来自 imageData 的 QR 码canvas.

class Webcam {
    constructor(videoTag, canvasTag) {
        // using for real-time video capture
        this.videoTag = videoTag;
        // qr scanner parses imageData from this element
        this.canvasTag = canvasTag;
        // waiting for qr code here
        this.captureArea = {
            x: 100,
            y: 60,
            width: 120,
            height: 120
        }

        // getting access to webcam
        navigator.mediaDevices
            .getUserMedia({
                video: true
            })
            .then(stream => this.videoTag.srcObject = stream)
            .catch(console.log);
    }

    capture() {
        setInterval(() => {
            let ctx = this.canvasTag.getContext('2d');
            ctx.drawImage(this.videoTag, 0, 0, 320, 240);
            // drawing capture area
            ctx.strokeStyle = 'red';
            // this arguments also should be passed into qr scanner
            ctx.strokeRect(
                this.captureArea.x,
                this.captureArea.y,
                this.captureArea.width,
                this.captureArea.height
            );
        }, 100);
    }
}

class QRScanner {
    constructor(canvas, router, captureArea) {
        this.canvas = canvas;
        this.router = router;
        this.captureArea = captureArea;
        this.qrCode = null;
    }

    scan() {
        setInterval(() => {
            let imageData = this.canvas
                .getContext('2d')
                .getImageData(
                    this.captureArea.x,
                    this.captureArea.y,
                    this.captureArea.width,
                    this.captureArea.height
                ).data;

            // parsing qr code from canvas
            this.qrCode = jsQR(imageData, this.captureArea.width, this.captureArea.height);

            if (this.qrCode) {
                router.redirect(Router.pages.result, this.qrCode);
                let resultPage = document.querySelector('#result .qr-code-data');
                resultPage.innerHTML = this.qrCode.data;
            }
        }, 100);
    }
}

<div id="scan">
    <video id="video" width="320" height="240" autoplay title="Real-time video stream from webcam"></video>
    <canvas id="preview" width="320" height="240" title="Capture area for QR code"></canvas>
</div>

这按预期工作,但是当我从页面中删除 canvas 元素并尝试使用临时 canvas(使用 document.createElement('canvas') 而不附加到页面)时 - 此解决方案不工作。是否可以使用临时 canvas 获取 video imageData 而无需将此 canvas 附加到页面?

P.S。我正在使用 https://github.com/cozmo/jsQR

Canvas 元素在未明确设置时具有默认宽度和高度。由于您从未为您创建的 canvas 设置它们,因此它将默认为 300 x 150,至少 Chrome 可能与其他浏览器实现不同。

var canvas = document.createElement("canvas");
console.log(canvas.width,canvas.height)

并且由于此默认大小与您尝试将 image/video 绘制到的大小不同,因此将进行一些裁剪,从而影响您的 QR 库正确读取图像。

只要设置你需要的宽度和高度就可以了

var canvas = document.createElement('canvas')
canvas.width = 320;
canvas.height = 240;