2017-06-22 2 views
0

Ich streame einen Webcam-Feed in ein video-Element und male das anschließend auf ein canvas-Element. Ich lasse dann einen Gesichtserkennungsalgorithmus auf der Leinwand laufen, um ein Quadrat über das Gesicht zu malen.Der Aufruf von context.getImgData() bewirkt, dass Canvas "flimmert"

Das Problem ist, dass, um dies zu tun, muss ich die context.getImgData() Methode aufrufen. Dies führt dazu, dass die Zeichenfläche beim Aufruf der Methode "flimmert". Es wird für einen Sekundenbruchteil komplett schwarz und kehrt dann zum Normalzustand zurück. Es sieht schrecklich aus. Ich habe einige Beispiele von anderen verfolgt, die Leinwände mit Webcam-Feeds gezeichnet haben, und sie verwenden auch diese Methode, so dass ich nicht wirklich weiß, wie ich es umgehen kann.

Ich habe einige Beispielcode unten, der in JSfiddle funktioniert. Ich bin auf Mac OS mit Firefox. Es gibt zwei Tasten. Der erste malt den Strom von dem video Element in den canvas, und der zweite läuft einfach getImgData(). Sie können das Problem, das ich beschreibe, deutlich sehen. Irgendwelche Gedanken?

<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

Ich kann nicht reproduzieren. Mit welchen Browsern und Betriebssystemen haben Sie getestet? – Watilin

+0

Sorry sollte geklärt haben - Mac OS und Firefox –

Antwort

0

Ok es heraus - wenn Sie schauen, die getImageData() Methode verwenden, um es innerhalb der gleichen Funktion wie die Auslosung genannt werden müssen.

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

Nein, kein Grund sollte es in der gleichen Funktion aufgerufen werden. Ihr Problem hat mehr mit Ihrer schrecklichen Schleife zu tun, verwenden Sie stattdessen rAF. Außerdem würden Sie wahrscheinlich gewinnen, indem Sie eine kleinere Leinwand außerhalb des Bildschirms behalten, auf der Sie eine geschrumpfte Version der Videobilder zeichnen würden, um die Erkennung auf einer kleineren Oberfläche durchzuführen. – Kaiido

Verwandte Themen