- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在尝试使用 Canvas 来编辑视频,方法是绘制到屏幕外 Canvas ,然后使用 getImageData 做一些工作,然后将其放入屏幕 Canvas 上。它可以工作,但即使是 480x360 的小视频,Chrome 内存使用量也会不断增加,直到崩溃(在我的机器上大约需要十分钟,较大视频的时间会更少)。该问题在 Firefox 中似乎有所改善,但内存使用量仍然较大。
我意识到每个 getImageData 调用都需要大约 3MB 的内存,但即便如此,我觉得应该有一种方法可以让 Chrome 使用少于 1GB 的内存。我降低了帧速率,这有帮助,但并不能解决问题。我能做些什么来确保更及时地释放 imageData 内存吗?
<!DOCTYPE html>
<meta charset='utf-8'>
<html>
<head>
<title>Video Test</title>
</head>
<body>
<canvas id='display'>
</canvas>
<script type='text/javascript'>
var canvas = document.getElementById('display');
var context = canvas.getContext('2d');
var bCanvas = document.createElement('canvas');
var bContext = bCanvas.getContext('2d');
var video = document.createElement('video');
video.src = 'VIDEO HERE';
video.autoplay = true;
video.loop = true;
var last;
var interval = 35;
video.addEventListener('play', function() {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
bCanvas.width = video.videoWidth;
bCanvas.height = video.videoHeight;
last = performance.now();
window.requestAnimationFrame(draw);
}, false);
function draw(time) {
if(time - last > interval) {
bContext.drawImage(video,0,0,bCanvas.width,bCanvas.height);
var imageData = bContext.getImageData(0,0,bCanvas.width,bCanvas.height);
context.putImageData(imageData,0,0);
last = time;
}
window.requestAnimationFrame(draw);
}
</script>
</body>
</html>
最佳答案
由于您想要实现的是色度键效果,因此您可以在下采样帧上进行色度检测,设置其透明度,然后在输出 Canvas 上以正常比例重新绘制它。
然后,由于输出上下文的 globalCompositeOperation
属性设置为 "destination-in"
,您可以仅绘制原始框架的不透明部分,保持其原始品质:
// Define our canvases
var output = document.createElement('canvas'),
ctx = output.getContext('2d'),
buffer = output.cloneNode(),
buf = buffer.getContext('2d');
document.body.appendChild(output);
var threshold = colorThreshold.value,
color = hexToRgb(colorInp.value.split('#')[1]);
var lastCall = 0;
function draw() {
requestAnimationFrame(draw);
// if the video is still at the same frame, we don't need to process anything
if (video.currentTime === lastCall)
return;
// video.pause();
lastCall = video.currentTime;
// clear our output canvas
ctx.clearRect(0, 0, output.width, output.height);
ctx.drawImage(video, 0, 0, output.width, output.height);
// draw a downsampled frame on the buffer canvas
buf.drawImage(video, 0, 0, buffer.width, buffer.height);
// get this downsampled canvas's imageData
var image = buf.getImageData(0, 0, buffer.width, buffer.height),
data = image.data;
var t = threshold / 2;
// loop through the imageData pixels
for (var i = 0; i < data.length; i += 4) {
// for a correct Chroma key, this should be improved
if ((color[0] - t) <= data[i] && data[i] <= (color[0] + t) &&
(color[1] - t) <= data[i + 1] && data[i + 1] <= (color[1] + t) &&
(color[2] - t) <= data[i + 2] && data[i + 2] <= (color[2] + t)) {
// set the alpha channel to 0
data[i + 3] = 0;
}
}
// redraw our now-tranparent image on the buffer
buf.putImageData(image, 0, 0);
// set our context's gCO to destination-in ...
ctx.globalCompositeOperation = 'destination-in';
// resample the buffer to a normal scale (bad quality)
ctx.drawImage(buffer, 0, 0, output.width, output.height);
// reset the context's gCO
ctx.globalCompositeOperation = 'source-over';
}
colorThreshold.addEventListener('input', function() {
threshold = this.value;
});
colorInp.addEventListener('input', function() {
color = hexToRgb(this.value.split('#')[1]);
});
cutQ.addEventListener('input', function() {
buffer.width = (output.width / 100) * this.value;
buffer.height = (output.height / 100) * this.value;
});
video.addEventListener('loadedmetadata', function() {
output.width = this.videoWidth;
output.height = this.videoHeight;
buffer.width = (output.width / 100) * cutQ.value;
buffer.height = (output.height / 100) * cutQ.value;
draw();
});
// convert our input's value to rgb
function hexToRgb(hex) {
var bigint = parseInt(hex, 16),
r = (bigint >> 16) & 255,
g = (bigint >> 8) & 255,
b = bigint & 255;
return [r, g, b];
}
canvas {
width:100%;
border: 1px solid;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGUlEQVQYlWP4z8DwHx0zYANDQeEgcw5FCgHKJ2OdLLDjkAAAAABJRU5ErkJggg=='), repeat;
}
Color to pick :
<input type="color" value="#30f062" id="colorInp" /><br>
Cut quality :
<input type="range" min="10" max="100" step=".5" value="80" id="cutQ" /><br>
Color Threshold :
<input type="range" min="0" max="255" step=".5" value="166" id="colorThreshold" /><br>
<video id="video" style="position:absolute;visibility:hidden;z-index:-1" autoplay="" muted="true" loop="true" src="https://dl.dropboxusercontent.com/s/1jp0f76yvzuucj7/L0ckergn0me-PixieGreenScreen446_512kb.mp4" crossorigin="anonymous"><!--CC BY-NC-SA 2.0 http://chris.pirillo.com/--></video>
关于javascript - 使用canvas编辑视频时如何减少getImageData的内存占用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33687775/
我所需要的只是获取 Canvas 上单个像素的状态,但我注意到它非常慢。 这是我的 JS var state = ctx.getImageData(x,y,1,1).data; state = 'rg
如何使用 .getImageData() 从给定元素的背景图像中获取数据?项目已经在使用 jQuery,因此欢迎使用 jQuery 解决方案。 最佳答案 getImageData方法只会为您提供来自c
当图像被绘制到 Canvas 中时,如何在js中使用getImageData()? (我分别需要每个图像的数据。) 最佳答案 这是一种方法: // get the imageData for the
这个问题在这里已经有了答案: Why does changing an Array in JavaScript affect copies of the array? (12 个答案) Pass-b
因此,我在 中创建的“上下文”变量上使用函数 getImageData。部分,当我做一些事情,比如画一个矩形然后做 ctx.getImageData.data[0] 它会显示我在 Canvas 上画
您好,我有这个脚本可以检查透明像素和非透明像素。现在我做到了,所以结果来自鼠标悬停在 100px x 100px 的矩形: var data = ctx.getImageData(100,100, c
我正在尝试从图像中输出像素值。图片加载正确;此处的另一个答案表明浏览器正在尝试在图像加载完成之前读取像素,但我可以看到它在 alert() 触发时已加载。 function initContext(c
先行者:我知道已经有人问过关于这个主题的几个问题,但似乎没有一个提供直接的纯 JavaScript 解决方案。 所以我在尝试使用context.getImageData()之类的东西从 Canvas
当下面的代码返回上一张上传的图片而不是当前图片的值时,有人可以告诉我哪里出了问题吗? var imageLoader = document.getElementById('imageLoade
我正在创建一个移动网络应用程序游戏,让用户可以在屏幕上滑动来清除它。我正在尝试编写一个智能函数来检测几乎整个 Canvas 何时是透明的。 我有一个间隔,每秒调用下面的函数来进行检查。它应该工作的方式
我正在尝试获取源 Canvas 的内容,对其进行剪辑,然后将其绘制到另一个 Canvas 上。即使我的代码在使用 src PNG/new Image() 组合时工作得很好,但当源内容来自另一个 Can
为了从特定坐标的图像中获取颜色,我使用了这个答案 get-pixel-color-from-canvas-on-mouseover .然而在Powerpoint在 Microsoft 的第 56 页上
我正在尝试覆盖内置方法 CanvasRenderingContext2D.getImageData()。我想重写实现,以便修改后的函数使用 Canvas 上下文修改 Canvas ,然后调用原始函数,
分析 HTML5 Canvas 中的像素数据: var width = 960; var height = 500; var canvas = document.getEle
缩小 Canvas 后,我遇到了 context.getImageData() 问题。我已将 Canvas 添加到 HTML 页面: 我在 Canvas 上绘制了图像,就像按钮一样。我正在测试 Alp
这个问题已经有答案了: Create Canvas element with image and append to parent (2 个回答) 已关闭 8 年前。 所以,我有一个这样的函数: va
我试图通过canvas标签读取图像数据,每次我尝试检索和显示该数据时,它都出现0。即使我将数据抓取限制为 1 个像素,它也会出现“0,0,0,0”。奇怪的是,我可以使用 fillRect 并检索该数据
由于上一篇文章太困惑,我在这里开了一个新线程。 我正在尝试使用 JavaScript 从我的服务器检索 .png 文件中的确切 RGBA 值。 代码如下: img = new Image(); img
我正在加载一个 PNG 并尝试检查它是否完全不透明,这意味着 alpha channel 在整个图像上接近 100%。因此,我使用 Canvas 和 2D-Context 来获取像素数据并循环检查
我正在尝试制作一个颜色选择器。我的代码在 getImageData 之后以某种方式停止。我找不到解决方案... 还有其他方法获取像素值吗?或者问题是我正在尝试使用图片的链接? > function d
我是一名优秀的程序员,十分优秀!