【问题标题】:Dominant color in video for each frame每帧视频中的主色
【发布时间】:2013-08-08 23:38:45
【问题描述】:

我想分析有关 LED 闪烁的视频 (mp4)。 背景通常为灰色,但 LED 的颜色可能会有所不同。 LED 在视频中的距离足够近,因此 LED 灯是画面的最大部分。 我找到了 Color-Thief,但它只用于图像而不是视频。 因为闪烁的频率也可能不同,所以我需要检查视频的每一帧的主色。

如果有人有任何想法,我将不胜感激。提前感谢您的宝贵时间。

编辑: 视频的两个屏幕截图(第一个红色 LED 关闭;第二个红色 LED 亮)(必须删除两个屏幕截图链接的偷色链接)

这是视频开始播放时调用的函数,应该分析视频。我尝试通过平均颜色来做到这一点,但这没用,因为那通常是某种灰色/棕色。

function processFrame(e) {  

    var video = document.getElementById("video");

    if (video.ended){
        //dauer();
        console.log("Ende");
        //alert("Ende");
    }

    if (video.paused || video.ended) {
        return;
    }

    var bufferCanvas = document.getElementById("buffer");
    var displayCanvas = document.getElementById("display");
    var buffer = bufferCanvas.getContext("2d");
    var display = displayCanvas.getContext("2d");

    buffer.drawImage(video, 0,0, bufferCanvas.width, displayCanvas.height);

    var frame = buffer.getImageData(sx, sy, sw, sh);
    var length = frame.data.length / 4;

    for (var i = 0; i < length; i++) {
        var r = frame.data[i * 4 + 0];
        var g = frame.data[i * 4 + 1];
        var b = frame.data[i * 4 + 2];
        average= average +((r+g+b)/3)       
    }   

    averagecolor[i]=average

    display.putImageData(frame, 0, 0);

    setTimeout(processFrame, 0);
}

【问题讨论】:

  • 请分享您迄今为止尝试过的内容,以便我们了解您在代码中遇到的问题。还请显示您要分析的视频的屏幕截图(只需使用 imgur.com 或一些并在您的帖子中插入链接)。一般来说,拍摄 LED/灯通常会导致中心被洗掉,这让您只剩下光环作为可用数据,因此要查看我们正在处理的内容,最好有图像。

标签: javascript html video canvas colors


【解决方案1】:

您的要求有点宽泛,因为您需要分几个步骤执行此操作 - 但完全可以做到。为了缩短篇幅,我将只介绍您需要采取的步骤,以便能够分析 LED。

您可以通过预定义视频帧中的区域来全自动或半自动执行此操作。

自动检测的步骤如下,每个会话使用一次,以防相机移动或变焦改变。照明条件也会影响检测,但在这里我将假设照明条件与您显示的图像相同。它也特定于这些图像,如果您更改路由器/相机的设置,它可能无法正常工作。

自动检测区域的初始步骤:

  • 当所有 RGB 值 = 255(即 LED 的白色中心)时,将水平线扫描到一半并开始注册区域。设置一个标志,表明您在一个区域中,并在您开始注册时根据阈值计算像素数(例如,需要连续为白色的 7-10 个像素)。这是为了消除单个像素,使之变成白色。
  • 当您在一条线上(基于阈值)末端区域找不到任何白色像素时,并准备进行新的配准。
  • 在前半部分底部时(我会设置一个比实际高度短的最大高度),从中间开始扫描到右边缘。

在此之后,您应该注册了六个区域(使用所有 LED 都亮起的“校准”框架 - 这可以在实时运行之前手动运行)。

对于将持续运行的下一步,您将使用这些区域作为锚区域,并仅在一侧采样点且高度仅为几个像素。

  • 使用区域作为锚点,并基于偏移量 x + 区域宽度 + 2 个像素作为起始 X 定义一个 样本区域(这只是初始偏移量的建议 - 你可能有微调这个)。偏移 Y + 10 并将宽度和高度设置为 10 像素。这应该会在 LED 旁边为您提供一个 100 点的样本区域。
  • 使用 getImageData 对这个小区域运行统计信息。您需要检查所有三个组件,因为您需要过滤掉浅灰色。找到一个阈值(例如if r &gt; 230 &amp;&amp; b &lt; 200 &amp;&amp; g &lt; 200 只是为了获取一些值),当你累积你的红色值(以及另一个用于绿色)时。这个过程需要一个校准阶段来找到您需要使用的阈值。运行一些测试。如果相机改变 f-stop,您可能需要重新校准。
  • 将绿色和红色值累积到不同的变量。您不需要对它们进行平均,但您需要为 total sum 找到一个阈值,在该阈值中,您知道该颜色的 LED 的 LED 亮起(使用区域检测中的初始测试帧为此也是如此)。通过比较 LED 关闭时的区域,为这些值添加一些容差。

如果您可以对其进行微调,这将使您总共只能扫描 600 个点,可能会更少。

对于手动方法,您可以跳过第一步中所述的区域设置,而是使用框架并通过测量白顶的像素手动设置区域。如果您更改相机位置,则需要重新设置。

据您了解,需要为此编写一些代码,并且有许多因素会影响最终代码,使其非常适合此用途。而且我相信它在一定程度上超出了 SO 的范围,但我希望这能给你一些帮助你前进的线索。

【讨论】:

  • 谢谢,我会尝试并回复您!
  • 你好乔纳斯,你成功了吗?我试图用视频做类似的事情......但没有成功。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多