使用 OpenCV 过滤波动光照

Filter fluctuating lighting with OpenCV

我需要使用 OpenCV 在网络摄像头镜头中进行相当敏感的颜色(亮度)测量。我遇到的问题是环境光波动,这使得很难获得准确的结果。我正在寻找一种方法来不断更新视频的连续帧以消除全局照明差异。我试图滤除的光线变化在大部分或全部图像中全局发生。我试图计算出差异并减去它,但运气不佳。有人对如何解决这个问题有什么建议吗?

编辑: 下面两张图片来自同一个视频,颜色变化略有放大。如果你在它们之间交替,你会看到光线有轻微的变化,可能是由于外面的云层移动。问题是这些变化掩盖了我可能想要检测的任何其他颜色变化。

所以我想过滤掉这些特定的更改。鉴于我只需要捕获的部分帧,我认为应该可以过滤掉其余镜头中发生的光照变化。在我感兴趣的领域之外。

我尝试使用 dft 捕捉变化中的主要频率,以简单地忽略光照变化。但是我对那个函数的使用还不够熟悉。我才用opencv一个星期,还在学习中

简短回答:整体照明的时间低通滤波器

从概念上讲,将照明视为一个值的时间序列,表示类似于照射到正在拍摄的场景上的光通量。您的理想情况是此函数保持不变,但次佳的情况是它尽可能缓慢地变化。 low-pass filter 将一个可以快速变化的函数更改为一个变化较慢的函数。因此,基本步骤是:(1)计算总光照函数(2)使用低通滤波器计算新的光照函数(3)将原始图像序列归一化为新的光照值。

(1) 计算光照函数的最简单方法是将图像中每个像素的所有亮度值相加。在简单的情况下,这甚至可能有效;你可能会从我的语气中猜到有很多注意事项。

一个重要的问题是您更愿意将光照值相加而不是某种颜色 space(例如 HSV),而是某种光照的物理量度。从颜色 space 返回到房间中的实际光线需要不在图像中的数据,例如图像中每个表面的光谱反射率,因此这不太可能。作为对此的代理,您可以仅使用图像的一部分,即具有一致反射率的图像。在示例图像中,可以使用图像顶部的桌面。 Select 一个几何区域并从中计算总照明数。

与此相关,如果图像中有相机饱和的区域,您将丢失大量信息,并且总照明值与物理照明的相关性不佳。只需剪掉任何此类区域(但在所有帧中始终如一地进行)。

(2) 计算光照函数的低通滤波器。这些变换是每个信号处理包的基本组成部分。我对 OpenCV 了解不够,无法知道它本身是否具有适当的功能,因此您可能需要另一个库。有很多不同种类的低通滤波器,但它们都会给您类似的结果。

(3) 获得低通时间序列后,您希望将其用作总光照的归一化函数。计算低通序列的平均值并除以它,得到平均值为 1 的时间序列。现在通过将图像中的光照乘以归一化因子来变换每个图像。所有关于在物理照明 space 而非颜色 space 下理想工作的警告均适用。

如果信号变化是全局性的,您应该尝试计算视频中时间 t 处每个图像中每行 i 的平均 m(i,t)。没有波动的光比 m(i,t)/m(i,t+1) 必须始终为 1。如果存在全局变化,则对于每个 i,m(i,t)/m(i,t+1) 必须保持不变。最好使用平均值 m(i,t)/m(i,t+1)(对于所有 i)。该平均值可用于校正您在时间 t 的图像。

你可以使用像 m(i,0)/m(i,t) 这样的比率,时间 0 的图像就是一个参考 您可以使用柱形或圆盘矩形代替线...

我认为您可以将 homomorphic filtering 应用于每个帧以计算帧的反射分量。然后您可以跟踪选定点的不同反射率。

根据成像的照度-反射率模型,给定位置的像素值是照度与反射率的乘积:f(x,y) = i(x,y) . r(x,y)。照明度 i 在整个图像(或在您的情况下,框架)上 往往变化缓慢 ,而反射率 r 往往变化迅速。

利用同态滤波,可以滤除光照分量。它取上述等式的对数,因此 ln 光照和反射分量变为相加:ln(f(x,y)) = ln(i(x,y)) + ln(r(x,y))。现在,您应用高通滤波器来保留反射分量(因此滤除缓慢变化的照明分量)。请查看 here and here 以获取带有示例的过程的详细说明。

应用滤镜后,您将获得估计的反射率帧 r^(x,y,t)