我设置了一个带有网络摄像头、HTML5 视频和画布的绿屏。我从 MDN 获得了一个关于创建色度键(绿屏)的想法。但是使用实时网络摄像头而不是预先录制的视频。一切都按预期工作,除了当我去保存图像时,色度键区域是白色而不是透明的。有一个海洋的背景。当网络摄像头打开并且一个人站在它前面时,看起来这个人就在大海中。同样,保存该图像只会给我一个白色的盒子,中间有我自己。网络摄像头尺寸为 640 x 480,画布尺寸为 1600 x 800。
编辑: 我将色度键容差更改为深灰色及以上。现在,如果您在相机前放一些白色的东西,理论上它应该显示整个背景图像。但它的左边有一个 640x480 的盒子,颜色与<body>
.
这是一个演示除非您在背景中有一些绿色,否则它不会真正起作用。仅限 Webkit。
网络摄像头色度键:
var processor = {
timerCallback: function() {
if (this.webcam.paused || this.webcam.ended) {
return;
}
this.computeFrame();
var self = this;
setTimeout(function () {
self.timerCallback();
}, 0);
},
doLoad: function() {
this.webcam = document.getElementById("webcam");
this.c1 = document.getElementById("c1");
this.ctx1 = this.c1.getContext("2d");
this.c2 = document.getElementById("c2");
this.ctx2 = this.c2.getContext("2d");
var self = this;
this.webcam.addEventListener("play", function() {
self.width = 640;
self.height = 480;
self.timerCallback();
}, false);
},
computeFrame: function() {
this.ctx1.drawImage(this.webcam, 0, 0, 640, 480); //draw webcam to canvas
var frame = this.ctx1.getImageData(0, 0, 640, 480); //capture a frame
var l = frame.data.length / 4;
for (var i = 0; i < l; i++) { //loop through pixels
var r = frame.data[i * 4 + 0];
var g = frame.data[i * 4 + 1];
var b = frame.data[i * 4 + 2];
if (g > 100 && r < 95 && b > 60 && b < 160 ){
frame.data[i * 4 + 3] = 0;
}
}
this.ctx2.putImageData(frame, 480, 300); //place chroma video over bg img
return;
}
};
脚本.js
processor.doLoad();
//more stuff runs
takePicture();
function takepicture() {
var canv = document.getElementById('c2');
var photo = document.querySelector('#inptPhoto');
var data = canv.toDataURL('image/png');
photo.setAttribute('src', data);
}
我遇到了另一个 SO 帖子,该帖子表明我的图像实际上可能不是透明的,而是背景中的白色,这与我的结果一致。还有另一种方法可以做到这一点吗?