我正在研究this paper中描述的GMG背景扣除算法。由于OpenCV 3.0还具有GMG算法的实现(作为附加包opencv_contrib),因此我尝试一起研究两者。但是,我不确定这两个参数maxFeatures
和quantizationLevels
的含义,因为我想将它们映射到本文的描述中。
引用OpenCV 3.0中的源代码(文件模块\ bgsegm \ src \ bgfg_gmg.cpp):
//! Total number of distinct colors to maintain in histogram.
int maxFeatures;
和
//! Number of discrete levels in each channel to be used in histograms.
int quantizationLevels;
并引用该论文(第II B部分)(由于此处不支持LaTex,因此修改了一些数学符号和变量名):
“...在T个观察到的特征中,选择F_tot F_max,则观察到的不同特征的数量F_tot可能会超过极限F_max。在这种情况下,我们丢弃最旧的观测值,以使F_tot
通过以上描述,我最初确信OpenCV 3.0中的
maxFeatures
指的是F_max,而quantizationLevels
指的是F_tot。但是,这听起来不对,原因有二:(1)本文提到“F_tot是观察到的不同特征的数量”,并且(2)OpenCV源代码在maxFeatures
和quantizationLevels
之间没有任何关系,尽管本文很清楚建议前者应大于或等于后者。那么,
maxFeatures
和quantizationLevels
的含义是什么? quantizationLevels
是OpenCV引入的用于计算直方图的参数吗? 最佳答案
在进一步研究OpenCV中的源代码之后,我相信maxFeatures
指的是F_max,而quantizationLevels
实际上是直方图中的bin数。原因如下:
在insertFeature()
函数中,该函数包含以下代码:
static bool insertFeature(unsigned int color, float weight, unsigned int* colors, float* weights, int& nfeatures, int maxFeatures)
{
int idx = -1;
for (int i = 0; i < nfeatures; ++i) {
if (color == colors[i]) {
// feature in histogram
weight += weights[i];
idx = i;
break;
}
}
if (idx >= 0) { // case 1
// move feature to beginning of list
::memmove(colors + 1, colors, idx * sizeof(unsigned int));
::memmove(weights + 1, weights, idx * sizeof(float));
colors[0] = color;
weights[0] = weight;
}
else if (nfeatures == maxFeatures) { // case 2
// discard oldest feature
::memmove(colors + 1, colors, (nfeatures - 1) * sizeof(unsigned int));
::memmove(weights + 1, weights, (nfeatures - 1) * sizeof(float));
colors[0] = color;
weights[0] = weight;
}
else { // case 3
colors[nfeatures] = color;
weights[nfeatures] = weight;
++nfeatures;
return true;
}
return false;
}
情况1:当颜色与
colors[]
数组中的一项匹配时,将获得相应的数组元素。情况2:当颜色与
colors[]
数组中的任何项目都不匹配并且达到maxFeatures
(nFeatures
存储数组中存储的项目数)时,将为新颜色删除最旧的功能。情况3:当颜色与
colors[]
数组中的任何项目都不匹配并且maxFeatures
尚未达到时,将颜色添加到数组的新项目中,并且nFeatures
递增1。因此,
maxFeatures
应该对应于论文中的F_max(最大特征数)。另外,在函数
apply()
中:static unsigned int apply(const void* src_, int x, int cn, double minVal, double maxVal, int quantizationLevels)
{
const T* src = static_cast<const T*>(src_);
src += x * cn;
unsigned int res = 0;
for (int i = 0, shift = 0; i < cn; ++i, ++src, shift += 8)
res |= static_cast<int>((*src - minVal) * quantizationLevels / (maxVal - minVal)) << shift;
return res;
}
此函数根据
src_
,maxVal
和minVal
的值将指针quantizationLevels
指向的像素的颜色强度映射到bin,这样,如果quantizationLevels
= q,则代码的结果为:static_cast<int>((*src - minVal) * quantizationLevels / (maxVal - minVal))
必须为[0,q-1]范围内的整数。但是,可能存在
cn
通道(例如,在RGB中,cn
= 3,因此,移位操作和可能的bin数量(表示为b)因此是quantizationLevels
等于cn
的幂。因此,如果b> F_max,我们必须舍弃(b-F_max)最旧的特征。因此,在OpenCV中,如果我们将
maxFeatures
设置为> = quantizationLevels
^ cn
,那么我们就不必丢弃最旧的功能,因为我们允许的存储箱数量足够多,或不同的独特功能也足够多。