javascript - 如何使用 canvas html5 摆脱闪烁的图像并清除以前的画布结果?
问题描述
我正在使用 html5 使用 drawImage() 在黑色图像上绘制人体姿势关键点。当我第一次上传视频时,它会正确绘制。但是当我上传第二个视频时,前一个视频的结果会被保留,而当前视频的结果会导致图像在绘制时闪烁。在代码下方找到 -
$(document).ready(function () {
let fileURL;
let file_ext;
let width, height;
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var image_bg;//document.getElementById('source');
let video;
// The detected positions will be inside an array
let poses = [];
let poseNet;
$("#selectVideoFile").filestyle({htmlIcon: '<span><i class="fa fa-search"></i></span> ',
size: "md",
text: ' Select',
btnClass : "btn btn-change",
placeholder: "Upload person video"
});
function isEmpty(obj) {
for(var key in obj) {
if(obj.hasOwnProperty(key))
return false;
}
return true;
}
function showInpVideo(input) {
if (!(isEmpty(fileURL))) {
URL.revokeObjectURL(fileURL);
}
var fileInput = document.getElementById('selectVideoFile');
fileURL = window.URL.createObjectURL(fileInput.files[0]);
$('#inputVideo').html("");
$('#inputVideo').append('<video controls id="video" src="'+ fileURL +'" alt="Input Video" width="620" height="360"></video>');
};
// Listen for the change event on our input element so we can
// get the video file selected by the user
document.getElementById('selectVideoFile').addEventListener('change', function(e) {
var fileName = $(".vidFile").val().replace(/C:\\fakepath\\/i, '');
file_ext = (fileName !== '') ? fileName.split(".")[1].toLowerCase() : '';
console.log('Video File extension: ', file_ext);
$('#inputVideo').html("");
$('#canvasVideo').html("");
console.log('On change video name: ', fileName);
$('.input-video-loader').hide();
// $('.processed-video-loader').hide();
$('#inputVideo').hide();
$('.caption-text-video-input').hide();
$('.caption-text-video-processed').hide();
$('#canvas').hide();
$('#displayVideos').hide();
$('#videoBtn').hide();
// If file is selected or file selected has extension mp4
if (($('#selectVideoFile').val() !== '') && (file_ext === 'mp4')) {
$('#displayVideos').show();
$('.caption-text-video-input').show();
$('.input-video-loader').show();
$('#inputVideo').show();
// Show input video
showInpVideo();
$('.input-video-loader').hide();
vidId = document.getElementById('video');
console.log('video: ', vidId);
height = $('#video').height();
width = $('#video').width();
mdlSetup(vidId);
console.log(width+' '+height);
} else {
$('#displayVideos').hide();
alert("Please upload person video file having extension -- (.mp4)!")
$('#selectVideoFile').val('');
}
});
function mdlSetup(vidId){
console.log('*** Model Setup ****');
video = vidId;
//Posenet
poseNet = ml5.poseNet(video, modelReady);
console.log('Model Loaded ');
poseNet.on('pose', gotPoses);
}
// A function to draw the video and poses into the canvas.
// This function is independent of the result of posenet
// This way the video will not seem slow if poseNet
// is not detecting a position
function drawVideoIntoCanvas() {
//ctx.clearRect(0, 0, 620, 360);
// console.log('Draw Canvas: ', ctx);
// Draw the video element into the canvas
ctx.drawImage(image_bg, 0, 0, 620, 360);
// We can call both functions to draw all keypoints and the skeletons
drawKeypoints();
drawSkeleton();
requestAnimationFrame(drawVideoIntoCanvas);
}
// A function that gets called every time there's an update from the model
function gotPoses(results) {
poses = results;
//console.log('Poses : ', poses)
}
function modelReady() {
// document.getElementById('status').innerHTML = 'Model Loaded'
console.log("model ready")
poseNet.multiPose(video);
}
// A function to draw ellipses over the detected keypoints
function drawKeypoints() {
// Loop through all the poses detected
for (let i = 0; i < poses.length; i=i+2) {
// For each pose detected, loop through all the keypoints
for (let j = 0; j < poses[i].pose.keypoints.length; j++) {
let keypoint = poses[i].pose.keypoints[j];
// Only draw an ellipse is the pose probability is bigger than 0.2
if (keypoint.score > 0.2) {
ctx.strokeStyle = 'rgb(0, ' + Math.floor(255 - 42.5 * i) + ', ' +
Math.floor(255 - 42.5 * j) + ')';
//ctx.strokeStyle = '#003300';
ctx.fillStyle = 'rgb(17, 240, 110)';
ctx.beginPath();
ctx.arc(keypoint.position.x, keypoint.position.y, 2, 0, 2 * Math.PI);
ctx.stroke();
}
}
}
}
// A function to draw the skeletons
function drawSkeleton() {
// Loop through all the skeletons detected
for (let i = 0; i < poses.length; i=i+2) {
// For every skeleton, loop through all body connections
for (let j = 0; j < poses[i].skeleton.length; j++) {
let partA = poses[i].skeleton[j][0];
let partB = poses[i].skeleton[j][1];
ctx.beginPath();
ctx.moveTo(partA.position.x, partA.position.y);
ctx.lineTo(partB.position.x, partB.position.y);
ctx.lineWidth = 2;
// set line color
ctx.strokeStyle = '#13f0c7'
ctx.stroke();
}
}
}
// video button controls
$('#play-btn').click(function(){
video.play();
});
$('#stop-btn').click(function() {
video.pause();
});
$('#reload-btn').click(function(){
video.load();
});
$('#refresh-btn').click(function(){
window.location.reload(true);
})
// on submit button click show canvas.
$('#btnVideoSubmit').click(function() {
console.log('-------On Execute Button Click-------');
console.log(width + ' ' + height);
console.log('video after sbmit: ', video);
// $('.processed-video-loader').show();
if (($('#selectVideoFile').val() !== '') && (file_ext === 'mp4')){
$('.caption-text-video-processed').show();
$('#canvas').show();
$('#videoBtn').show(200);
image_bg = new Image();
image_bg.onload = function(){
drawVideoIntoCanvas();
};
image_bg.src = 'https://www.ehotelsasia.com/wp-content/uploads/2018/10/Black-Background-DX58.jpg';
console.log('image_bg src:', image_bg.src);
// Loop over the drawVideoIntoCanvas function
//drawVideoIntoCanvas();
} else {
$('#displayVideos').hide();
alert("Please upload person video file having extension -- (.mp4)!")
}
})
/// --------------------- End -----------------------
//document.getElementById('clear').addEventListener('click', function(){
//ctx.clearRect(image_bg, 0, 0, 640, 375);
//})
});
解决方案
推荐阅读
- windows - POSIX 系统和/或 Windows 的 SCS_POSIX_BINARY 的字长(“位”)是多少
- azure - 让虚拟机认为鼠标在移动
- flutter - 当我调用一个函数“'Future”时,我在颤动中遇到了这个问题
'不能分配给参数类型'String'" - algorithm - 查找集合列表中是否有任何具有唯一元素的组合 <=2
- python - 无法使用 pyodbc 在 SQL 数据库中插入条目
- javascript - 我的 npm 包依赖于 X(比如它的 material-ui),如何避免用户安装 X 两次?
- function - 我在使用 Haskell 时遇到了我找不到的错误
- javascript - javascript:如何在Javascript中将字符串数字转换为数字而不删除点后的任何数字?
- xamarin.forms - 从子视图更新父视图上的 OnPropertyChanged
- c - 链表字段添加