我正在使用 https://github.com/auduno/clmtrackr
我正在尝试从以下示例中获取要保存的图像: https://github.com/auduno/clmtrackr/blob/dev/examples/facedeform.html
问题是我显然已经尝试过“canvas.dataToURL()”。我可以将网络摄像头的视频作为图像获取;但是,叠加图像始终是透明的。
我尝试使用纹理在 Canvas 上绘图,但这也没有用....
我这里有一个例子:https://codepen.io/msj121/pen/RgXjYK
我想将带有叠加层的整个图像保存为 png,就像我想的“dataToURL”。
// when everything is ready, automatically start everything ?
var vid = document.getElementById('videoel');
var vid_width = vid.width;
var vid_height = vid.height;
var overlay = document.getElementById('overlay');
var overlayCC = overlay.getContext('2d');
var webgl_overlay = document.getElementById('webgl');
// canvas for copying videoframes to
var videocanvas = document.createElement('CANVAS');
videocanvas.width = vid_width;
videocanvas.height = vid_height;
/*********** Setup of video/webcam and checking for webGL support *********/
var videoReady = false;
var imagesReady = false;
function enablestart() {
if (videoReady && imagesReady) {
var startbutton = document.getElementById('startbutton');
startbutton.value = "start";
startbutton.disabled = null;
}
}
$(window).load(function() {
imagesReady = true;
enablestart();
});
var insertAltVideo = function(video) {
if (supports_video()) {
if (supports_webm_video()) {
video.src = "./media/cap13_edit2.webm";
} else if (supports_h264_baseline_video()) {
video.src = "./media/cap13_edit2.mp4";
} else {
return false;
}
fd.init(webgl_overlay);
return true;
} else return false;
}
// check whether browser supports webGL
var webGLContext;
var webGLTestCanvas = document.createElement('canvas');
if (window.WebGLRenderingContext) {
webGLContext = webGLTestCanvas.getContext('webgl') || webGLTestCanvas.getContext('experimental-webgl');
if (!webGLContext || !webGLContext.getExtension('OES_texture_float')) {
webGLContext = null;
}
}
if (webGLContext == null) {
alert("Your browser does not seem to support WebGL. Unfortunately this face mask example depends on WebGL, so you'll have to try it in another browser. :(");
}
function gumSuccess( stream ) {
// add camera stream if getUserMedia succeeded
if ("srcObject" in vid) {
vid.srcObject = stream;
} else {
vid.src = (window.URL && window.URL.createObjectURL(stream));
}
vid.onloadedmetadata = function() {
// resize overlay and video if proportions are different
var proportion = vid.videoWidth/vid.videoHeight;
vid_width = Math.round(vid_height * proportion);
vid.width = vid_width;
overlay.width = vid_width;
webgl_overlay.width = vid_width;
videocanvas.width = vid_width;
fd.init(webgl_overlay);
vid.play();
}
}
function gumFail() {
// fall back to video if getUserMedia failed
insertAltVideo(vid);
alert("There was some problem trying to fetch video from your webcam, using a fallback video instead.");
}
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL || window.msURL || window.mozURL;
// check for camerasupport
if (navigator.mediaDevices) {
navigator.mediaDevices.getUserMedia({video : true}).then(gumSuccess).catch(gumFail);
} else if (navigator.getUserMedia) {
navigator.getUserMedia({video : true}, gumSuccess, gumFail);
} else {
insertAltVideo(vid);
alert("Your browser does not seem to support getUserMedia, using a fallback video instead.");
}
vid.addEventListener('canplay', function() {videoReady = true;enablestart();}, false);
/*********** Code for face substitution *********/
var animationRequest;
var positions;
var ctrack = new clm.tracker();
ctrack.init(pModel);
function startVideo() {
// start video
vid.play();
// start tracking
ctrack.start(vid);
// start drawing face grid
drawGridLoop();
}
var fd = new faceDeformer();
var mouth_vertices = [
[44,45,61,44],
[45,46,61,45],
[46,60,61,46],
[46,47,60,46],
[47,48,60,47],
[48,59,60,48],
[48,49,59,48],
[49,50,59,49],
[50,51,58,50],
[51,52,58,51],
[52,57,58,52],
[52,53,57,52],
[53,54,57,53],
[54,56,57,54],
[54,55,56,54],
[55,44,56,55],
[44,61,56,44],
[61,60,56,61],
[56,57,60,56],
[57,59,60,57],
[57,58,59,57],
[50,58,59,50],
];
var extendVertices = [
[0,71,72,0],
[0,72,1,0],
[1,72,73,1],
[1,73,2,1],
[2,73,74,2],
[2,74,3,2],
[3,74,75,3],
[3,75,4,3],
[4,75,76,4],
[4,76,5,4],
[5,76,77,5],
[5,77,6,5],
[6,77,78,6],
[6,78,7,6],
[7,78,79,7],
[7,79,8,7],
[8,79,80,8],
[8,80,9,8],
[9,80,81,9],
[9,81,10,9],
[10,81,82,10],
[10,82,11,10],
[11,82,83,11],
[11,83,12,11],
[12,83,84,12],
[12,84,13,12],
[13,84,85,13],
[13,85,14,13],
[14,85,86,14],
[14,86,15,14],
[15,86,87,15],
[15,87,16,15],
[16,87,88,16],
[16,88,17,16],
[17,88,89,17],
[17,89,18,17],
[18,89,93,18],
[18,93,22,18],
[22,93,21,22],
[93,92,21,93],
[21,92,20,21],
[92,91,20,92],
[20,91,19,20],
[91,90,19,91],
[19,90,71,19],
[19,71,0,19]
]
function drawGridLoop() {
// get position of face
positions = ctrack.getCurrentPosition();
overlayCC.clearRect(0, 0, vid_width, vid_height);
if (positions) {
// draw current grid
ctrack.draw(overlay);
}
// check whether mask has converged
var pn = ctrack.getConvergence();
if (pn < 0.4) {
drawMaskLoop();
} else {
requestAnimFrame(drawGridLoop);
}
}
function drawMaskLoop() {
videocanvas.getContext('2d').drawImage(vid,0,0,videocanvas.width,videocanvas.height);
var pos = ctrack.getCurrentPosition();
if (pos) {
// create additional points around face
var tempPos;
var addPos = [];
for (var i = 0;i < 23;i++) {
tempPos = [];
tempPos[0] = (pos[i][0] - pos[62][0])*1.3 + pos[62][0];
tempPos[1] = (pos[i][1] - pos[62][1])*1.3 + pos[62][1];
addPos.push(tempPos);
}
// merge with pos
var newPos = pos.concat(addPos);
var newVertices = pModel.path.vertices.concat(mouth_vertices);
// merge with newVertices
newVertices = newVertices.concat(extendVertices);
fd.load(videocanvas, newPos, pModel, newVertices);
var parameters = ctrack.getCurrentParameters();
for (var i = 6;i < parameters.length;i++) {
parameters[i] += ph['component '+(i-3)];
}
positions = ctrack.calculatePositions(parameters);
overlayCC.clearRect(0, 0, vid_width, vid_height);
if (positions) {
// add positions from extended boundary, unmodified
newPos = positions.concat(addPos);
// draw mask on top of face
fd.draw(newPos);
}
}
animationRequest = requestAnimFrame(drawMaskLoop);
}
/*********** Code for stats **********/
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
document.getElementById('container').appendChild( stats.domElement );
document.addEventListener("clmtrackrIteration", function(event) {
stats.update();
}, false);
/********** parameter code *********/
var pnums = pModel.shapeModel.eigenValues.length-2;
var parameterHolder = function() {
for (var i = 0;i < pnums;i++) {
this['component '+(i+3)] = 0;
}
this.presets = 0;
};
var ph = new parameterHolder();
var gui = new dat.GUI();
var presets = {
"unwell" : [0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"inca" : [0, 0, -9, 0, -11, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0],
"cheery" : [0, 0, -9, 9, -11, 0, 0, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0],
"dopey" : [0, 0, 0, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0],
"longface" : [0, 0, 0, 0, -15, 0, 0, -12, 0, 0, 0, 0, 0, 0, -7, 0, 0, 5],
"lucky" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 0, -6, 12, 0, 0],
"overcute" : [0, 0, 0, 0, 16, 0, -14, 0, 0, 0, 0, 0, -7, 0, 0, 0, 0, 0],
"aloof" : [0, 0, 0, 0, 0, 0, 0, -8, 0, 0, 0, 0, 0, 0, -2, 0, 0, 10],
"evil" : [0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, -8],
"artificial" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, -16, 0, 0, 0, 0, 0],
"none" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
};
var control = {};
var eig = 0;
for (var i = 0;i < pnums;i++) {
eig = Math.sqrt(pModel.shapeModel.eigenValues[i+2])*3
control['c'+(i+3)] = gui.add(ph, 'component '+(i+3), -5*eig, 5*eig).listen();
}
/********** defaults code **********/
function switchDeformedFace(e) {
//var split = ph.presets.split(",");
for (var i = 0;i < pnums;i++) {
ph['component '+(i+3)] = presets[e.target.value][i];
}
}
document.getElementById('deform').addEventListener('change', switchDeformedFace, false);
for (var i = 0;i < pnums;i++) {
ph['component '+(i+3)] = presets['unwell'][i];
}
最佳答案
webgl canvas 为空白的原因已在 stackoverflow 上至少回答了 10 次
Saving canvas to image via canvas.toDataURL results in black rectangle
Canvas toDataURL() returns blank image only in Firefox
toDataURL() of webgl canvas returning transparent image
Why does my canvas go blank after converting to image?
我知道还有好几个,但是我懒得全部搜索了
我没有将其标记为重复的唯一原因是因为您想要 2 个 Canvas 中的 1 个 png。
如果您只需要 1 个 png,那么您需要从一个 Canvas 上捕获。因此,将 WebGL Canvas 绘制到视频 Canvas 中,然后在视频 Canvas 上调用 toDataURL
。
const vctx = videocanvas.getContext('2d');
vctx.drawImage(webGLTestCanvas, 0, 0);
const capturedImage = videocanvas.toDataURL();
关于javascript - HTML 将 WebGL Canvas 保存为图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45221542/