Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 调用context.getImgData()会导致画布;闪烁“;_Javascript_Html_Canvas_Html5 Canvas - Fatal编程技术网

Javascript 调用context.getImgData()会导致画布;闪烁“;

Javascript 调用context.getImgData()会导致画布;闪烁“;,javascript,html,canvas,html5-canvas,Javascript,Html,Canvas,Html5 Canvas,我正在将一个网络摄像头提要流式传输到视频元素,然后将其绘制到画布元素上。然后我在画布上运行人脸检测算法,在人脸上画一个正方形 问题是要做到这一点,我需要调用context.getImgData()方法。这会导致调用该方法时画布“闪烁”。它在一瞬间完全变黑,然后恢复正常。看起来糟透了。我跟随了一些其他人的例子,他们用网络摄像头的feed在画布上画画,他们也使用这种方法,所以我真的不知道有什么方法可以绕过它 下面有一些在JSFIDLE中工作的示例代码。我在mac操作系统上使用firefox。有两个按

我正在将一个网络摄像头提要流式传输到
视频
元素,然后将其绘制到
画布
元素上。然后我在画布上运行人脸检测算法,在人脸上画一个正方形

问题是要做到这一点,我需要调用
context.getImgData()
方法。这会导致调用该方法时画布“闪烁”。它在一瞬间完全变黑,然后恢复正常。看起来糟透了。我跟随了一些其他人的例子,他们用网络摄像头的feed在画布上画画,他们也使用这种方法,所以我真的不知道有什么方法可以绕过它

下面有一些在JSFIDLE中工作的示例代码。我在mac操作系统上使用firefox。有两个按钮。第一个将流从
video
元素绘制到
canvas
,第二个只运行
getImgData()
。你可以清楚地看到我所描述的问题。有什么想法吗

<body>
    <div>
        <button onclick="paintCanvas()">paint</button>
        <button onclick="testFunc()">test</button>
    </div>
    <div>
        <canvas id="canvas" width="500" height="375"></canvas>
        <video autoplay loop="false" src="media/vid.mp4" type="video/mp4" id="videoElement">
    </div>
</body>
<script>
    var video = document.querySelector("#videoElement");
    var myCanvas = document.getElementById('canvas');
    var myContext = myCanvas.getContext('2d');

    navigator.mediaDevices.getUserMedia({ video: true })
        .then((stream) => {
            video.srcObject = stream;
            // vid2.srcObject = stream;
            // document.getElementById('controls').innerHTML = "Switch back to video for player controls";
            // document.getElementById('timing').innerHTML = '';
        })
        .catch(function (err) {
            media = 'video';
            console.log(err.name);
        });
    let ch, cw;
    function paintCanvas(e) {
        console.log('painting canvas')
        const v = document.getElementById('videoElement');
        const canvas = document.getElementById('canvas');
        const context = canvas.getContext('2d');
        cw = Math.floor(canvas.clientWidth);
        ch = Math.floor(canvas.clientHeight);
        canvas.width = cw;
        canvas.height = ch;

        draw(v, context, cw, ch);
    }
    function draw(v, c, w, h) {
        // console.log('drawing')
        videoRunning = true;
        if (v.paused || v.ended) return false;
        c.drawImage(v, 0, 0, w, h);
        myVar = setTimeout(draw, 60, v, c, w, h);
    }
    function testFunc() {       
        // setInterval(function () {
            console.log(video.videoWidth, video.videoHeight)
            x = myContext.getImageData(0, 0, video.videoWidth, video.videoHeight);
            console.log(x);
        // }, 200);
    }
</script>

油漆
测试
var video=document.querySelector(“#videoElement”);
var myCanvas=document.getElementById('canvas');
var myContext=myCanvas.getContext('2d');
navigator.mediaDevices.getUserMedia({video:true})
。然后((流)=>{
video.srcObject=流;
//vid2.srcObject=流;
//document.getElementById('controls').innerHTML=“切换回播放器控件的视频”;
//document.getElementById('timing').innerHTML='';
})
.catch(函数(err){
媒体=‘视频’;
console.log(错误名称);
});
让ch,cw;
功能画布(e){
console.log('绘制画布')
const v=document.getElementById('videoElement');
const canvas=document.getElementById('canvas');
const context=canvas.getContext('2d');
cw=数学地板(canvas.clientWidth);
ch=数学地板(帆布、床垫重量);
canvas.width=cw;
canvas.height=ch;
绘制(v、上下文、cw、ch);
}
功能图(v、c、w、h){
//console.log('drawing')
videoRunning=true;
如果(暂停| |结束)返回false;
c、 绘图图像(v,0,0,w,h);
myVar=设置超时(绘图,60,v,c,w,h);
}
函数testFunc(){
//setInterval(函数(){
console.log(video.videoWidth、video.videoHeight)
x=myContext.getImageData(0,0,video.videoWidth,video.videoHeight);
控制台日志(x);
// }, 200);
}

好的-如果要使用
getImageData()
方法,则必须在与绘图相同的函数中调用它

function draw(v, c, w, h) {
    // console.log('drawing')
    videoRunning = true;
    if (v.paused || v.ended) return false;
    c.drawImage(v, 0, 0, w, h);
    myVar = setTimeout(draw, 60, v, c, w, h);
    x = myContext.getImageData(0, 0, video.videoWidth, video.videoHeight)

}

我无法复制。你用什么浏览器和操作系统进行了测试?对不起,我应该澄清一下-mac os和firefoxNope没有理由在同一个函数中调用它。你的问题更多地与你糟糕的循环有关,改用rAF。此外,您可能会通过保留较小的屏幕外画布来获胜,您可以在画布上绘制缩小版的视频帧,以便在较小的表面上进行检测。