2017-06-22 135 views
0

我正在將網絡攝像頭數據流傳送到video元素,然後將其繪製到canvas元素上。然後,我在畫布上運行人臉檢測算法,在臉上繪製正方形。調用context.getImgData()會導致畫布「閃爍」

問題是,要做到這一點,我需要調用context.getImgData()方法。這會導致畫布在調用方法時「閃爍」。它瞬間完全變黑,然後恢復正常。它看起來很可怕。我跟着其他一些用網絡攝像頭動畫繪製畫布的人的例子,他們也使用這種方法,所以我真的不知道解決它的一種方法。

我在JSfiddle下面有一些示例代碼。我在使用Firefox的Mac OS上。有兩個按鈕。第一個將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> 
+1

我無法複製。你測試了哪些瀏覽器和操作系統? – Watilin

+0

對不起應該澄清 - mac os和firefox –

回答

0

好它了 - 如果你正在尋找使用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) 

} 
+0

不應該沒有理由它應該在同一個函數中調用。你的問題有更多的與你的可怕的循環,使用RAF代替。此外,通過保留一個更小的屏幕外畫布,您可能會獲勝,在這個畫布上您可以繪製視頻幀的縮小版以在較小的表面上進行檢測。 – Kaiido