我观看了以下教程https://youtu.be/BTWPDboW38o?si=_21TOjCfrXC3VWIL并尝试了同样的操作。我期望的是,我想根据视频流的颜色更改文档的背景颜色。但它总是返回 rgb(0,0,0)。
'use strict';
try {
const w = window,
d = document,
ng = navigator,
id = e => {
return d.getElementById(e)
},
cn = id('lh'),
i = id('i'),
o = id('o'),
cx = cn.getContext('2d', {
willReadFrequently: true
}),
face = r => ng.mediaDevices.getUserMedia({
video: {
facingMode: {
exact: 'user'
}
}
}).then(s => {
i.srcObject = s;
i.onloadedmetadata = e => {
setInterval(() => {
let c = 0,
k = -4,
h = cn.height = i.videoHeight,
w = cn.width = i.videoWidth,
dt = cx.getImageData(0, 0, w, h),
io = dt.data,
dl = io.length,
R, G, B;
R = G = B = 0;
cx.drawImage(i, 0, 0, w, h);
o.src = cn.toDataURL('image/webp');
while ((k += r * 4) < dl) {
++c;
R += io[k];
G += io[k + 1];
B += io[k + 2]
};
['R', 'G', 'B'].forEach(e1 => {
eval(e1 + '=' + `~~(${e1}/c)`)
});
let rgb = `rgb(${R},${G},${B})`;
d.body.style.background = rgb
}, -1)
}
});
face(4)
} catch (e) {
alert(e)
}
我希望它应该根据视频流改变文档的背景颜色。
好吧,你的代码实际上有很多错误
分配视频元素的 srcObject 后,您必须调用 play
在 setInterval 中,您在 let 语句中获取图像数据,但您已将任何内容绘制到画布上
当您实际调用face(4)时,您不会将r变量传递给then函数
当您使用数组 e1 的内容调用 eval 时,实际上保存的是字母“R”、“G”、“B”而不是它们的值
我不确定您实际上想通过 eval 实现什么目的,请参阅 按位非运算符 (~)
'use strict';
var timer;
var stream;
document.querySelector('input[value=stop]').onclick = e=>{
clearInterval(timer);
if(stream)stream.getTracks().forEach(track=>track.stop());
}
try {
const w = window,
d = document,
ng = navigator,
id = e => {
return d.getElementById(e)
},
cn = id('lh'),
i = id('i'),
o = id('o'),
cx = cn.getContext('2d', {
willReadFrequently: true
}),
face = r => ng.mediaDevices.getUserMedia({
video: {width:100,height:100}
}).then(s => {
stream=s;
i.srcObject = s;
i.play();
i.onloadedmetadata = e => {
timer=setInterval(() => {
let c = 0,
k = -4,
h = cn.height = i.videoHeight,
w = cn.width = i.videoWidth;
cx.drawImage(i, 0, 0, w, h);
let dt = cx.getImageData(0, 0, w, h),
io = dt.data,
dl = io.length,
R, G, B;
R = G = B = 0;
o.src = cn.toDataURL('image/webp');
while ((k += 4) < dl) {
++c;
R += io[k];
G += io[k + 1];
B += io[k + 2]
};
R/=c;
G/=c;
B/=c;
/*
['R', 'G', 'B'].forEach(e1 => {
eval(e1 + '=' + `~~(${e1}/c)`)
});
*/
let rgb = `rgb(${R},${G},${B})`;
d.body.style.background = rgb
}, -1)
}
});
face(4)
} catch (e) {
alert(e)
}
canvas {
border:1px solid lightgray;
}
video {
border:1px solid lightgray;
}
img {
border:1px solid lightgray;
}
input {
font-size:16px;
padding:5px;
}
<canvas id=lh></canvas>
<video id=i></video>
<img id=o>
<input type=button value=stop>
我添加了停止功能,因此可以通过重新加载页面来关闭它
我担心它实际上不会在 stackoverflow 网站上运行,我认为他们必须关闭网络摄像头访问并且不允许播放视频
我为以后访问此页面的任何人创建了一个更简洁的版本
var stream = await navigator.mediaDevices.getUserMedia({
video : true
});
var video = document.createElement('video');
video.srcObject = stream;
video.play();
update();
function update(){
gen.update();
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(video,0,0,canvas.width,canvas.height);
var data = ctx.getImageData(0,0,canvas.width,canvas.height);
var n = data.data.length;
var r = 0;
var g = 0;
var b = 0;
for(var i=0;i<n;i+=8){
r += data.data[i]/n*4;
g += data.data[i+1]/n*4;
b += data.data[i+2]/n*4;
}//for
document.body.style.background = `rgb(${r},${g},${b})`;
if(abort)return;
requestAnimationFrame(update,1000/framerate);
}//update