我将网络摄像头Feed流式传输到video
元素,然后将其绘制到canvas
元素上。然后我在画布上运行一个人脸检测算法,在脸上画一个正方形。
问题是要执行此操作,我需要调用context.getImgData()
方法。这导致画布闪烁"闪烁"调用方法时它瞬间变成全黑,然后恢复正常。看起来很糟糕。我已经关注了其他一些使用网络摄像头进行画布的人的例子,他们也使用这种方法,所以我真的不知道如何绕过它。
我在JSfiddle下面有一些示例代码。我在mac OS上使用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>
答案 0 :(得分: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)
}