来自视频帧的画布中的drawImage改变色调

Posted

技术标签:

【中文标题】来自视频帧的画布中的drawImage改变色调【英文标题】:drawImage in canvas from a video frame change the hue 【发布时间】:2018-02-03 15:51:44 【问题描述】:

我编写了一个简单的脚本,它从视频中提取一帧并将其绘制到画布上。我的问题是视频和绘制的图像之间的颜色正在变化。

我将结果放在原件旁边,以便于查看。原来的在左边。顺便说一句,它似乎在 chrome 浏览器上更明显。我在 OSX 上进行的所有测试。

这是一个 sn-p,左边是画布,右边是视频:

 // Get our mask image
var canvas = document.querySelector(".canvas");
var video = document.querySelector(".video");

var ctx = canvas.getContext('2d');
function drawMaskedVideo() 
  ctx.drawImage(video, 0, 0, video.videoWidth/2, video.videoHeight, 0,0, video.videoWidth/2,  video.videoHeight);


requestAnimationFrame(function loop() 
  drawMaskedVideo();
  requestAnimationFrame(loop.bind(this));
);
html, body 
  margin: 0 auto;

.video, .canvas 
  width: 100%;


.canvas 
  position: absolute;
  top: 0;
  left: 0;
<video class="video" autoplay="autoplay" muted="muted" preload="auto" loop="loop">
    <source src="http://mazwai.com/system/posts/videos/000/000/214/original/finn-karstens_winter-wonderland-kiel.mp4" type="video/mp4">
</video>
<canvas class='canvas' width='1280' height='720'></canvas>

我想知道为什么会发生这种情况,以及是否可以通过跨浏览器的方式摆脱它?

这是我写的简单脚本:

let video = document.querySelector('#my-video') // .mp4 file used
let w = video.videoWidth;
let h = video.videoHeight;
let canvas = document.createElement('canvas');
    canvas.width  = w;
    canvas.height = h;
let ctx = canvas.getContext('2d');

ctx.drawImage(video, 0, 0, w, h)

document.querySelector('.canvas-container').appendChild(canvas);

【问题讨论】:

您使用的是什么操作系统,视频层(在硬件/系统中)是否有单独的设置(颜色校正)?找到解决方法可以解释目的(您可以将整个视频帧绘制到画布中并仅处理其中的一部分)。 @K3N 我在 OSX 上,我从未设置过特定的颜色校正。目的是使视频帧模糊。由于 IE 兼容性,我不能使用 CSS3 解决方案。我可以通过画布播放视频而不是视频,但对于 CPU 来说似乎有点重,并且画布中的颜色会改变原始颜色。 您是否检查过这是否是画布的 alpha 处理问题? let ctx = canvas.getContext('2d', alpha: true);let ctx = canvas.getContext('2d', alpha: false); @Bellian 是的,两个值的结果相同 这听起来更像是视频在浏览器中具有不同的颜色,而不是画布在浏览器中具有不同的颜色。看看这两个线程是否有帮助:***.com/questions/28026976/…***.com/questions/35214962/… 【参考方案1】:

解决方案可能很简单,只需将 css filter 设置为视频元素:

.video 
    -webkit-filter: contrast(100%);

我无法对此进行推理,因为它是偶然发现的(玩你的演示并阅读相关答案),所以我将技术解释留给其他人,暂时给你一些魔法。

任何足够先进的技术都与魔法无异。

— 亚瑟 C. 克拉克

 // Get our mask image
var canvas = document.querySelector(".canvas");
var video = document.querySelector(".video");

var ctx = canvas.getContext('2d');
function drawMaskedVideo() 
  ctx.drawImage(video, 0, 0, video.videoWidth/2, video.videoHeight, 0,0, video.videoWidth/2,  video.videoHeight);


requestAnimationFrame(function loop() 
  drawMaskedVideo();
  requestAnimationFrame(loop.bind(this));
);
html, body 
  margin: 0 auto;

.video, .canvas 
  width: 100%;

.video 
  -webkit-filter: contrast(100%);


.canvas 
  position: absolute;
  top: 0;
  left: 0;
<video class="video" autoplay="autoplay" muted="muted" preload="auto" loop="loop">
    <source src="http://mazwai.com/system/posts/videos/000/000/214/original/finn-karstens_winter-wonderland-kiel.mp4" type="video/mp4">
</video>
<canvas class='canvas' width='1280' height='720'></canvas>

注意: 在 Macbook Pro(2,3 GHz Intel Core i5)上运行它,我看不出性能上有什么不同。在视频播放期间跟踪 CPU,两个演示的空闲率都在 28% 左右。

【讨论】:

以上是关于来自视频帧的画布中的drawImage改变色调的主要内容,如果未能解决你的问题,请参考以下文章

ReactJS画布drawImage不显示html5视频元素

HTML5 drawimage 从视频到画布

canvas中的drawImage

画布:drawImage 方法失败且没有错误

在 Firefox 中的画布上下文对象上使用 svg 调用 drawImage() 时出现问题

JavaScript将视频并入画布框