MeanShift公式理解
MeanShift formula understanding
我正在实施用于对象跟踪的 MeanShift 算法,使用来自此处的想法:http://www.cse.psu.edu/~rtc12/CSE598C/meanShiftColor.pdf
现在我有了后续帧的反投影图像。此类图像中的每个像素标记属于跟踪对象的概率:
上述来源中的 MeanShift 公式看起来是这样的:
w(xi) = 反投影图像中的像素。
x = 当前中心像素。
我不明白什么是spatial kernel
。
假设它可以是大小为 5x5 的二维高斯核,K(xi-x)*w(xi)可以用 pre-blurred 图像的像素替换。
我的代码看起来是这样的:
fvect2 findMeanShift(const PlainImage<uint8>& weights_smoothed, fvect2 old_center, DebugOutput& debug)
{
//LOGE("first center: %.2f %.2f", old_center.x, old_center.y);
const int w=weights_smoothed.getWidth(), h=weights_smoothed.getHeight();
int iter_count = 0;
fvect2 total_shift(0.0,0.0);
while(iter_count++ < 20)
{
fvect2 fTop(0,0);
float fBottom=0.0;
for(int y=0;y<h;++y)
for(int x=0;x<w;++x)
{
fvect2 cur_center(x, y);
float mult = weights_smoothed.at(x, y)[0]/255.0;
fBottom += mult;
fTop += (cur_center-old_center) * mult;
}
fvect2 mean_shift = fTop/fBottom;
//printf("mean_shift: %.2f %.2f", mean_shift.x, mean_shift.y);
debug.addArrow(old_center, old_center+mean_shift);
old_center += mean_shift;
//printf("old_center: %.2f %.2f", old_center.x, old_center.y);
total_shift += mean_shift;
if(mean_shift.lengthF()<0.1)
break;
}
return total_shift;
}
所以我只是通过平滑的反投影图像进行迭代,并且对于每个像素:
将其值添加到分母
将其值乘以从当前中心到分母的偏移。
第二次迭代收敛了,但是shift错了,不知道怎么debug。可能是公式实现的问题。
请用人类语言向我解释什么是空间核以及如何将其应用于权重图像。谢谢!
嗯,我明白了。空间掩码是搜索window。反向投影不需要模糊。应用于整个图像,1
在搜索内部 window,0
在外部。在this的第2页有更简单的解释。
如果在远离跟踪对象的地方搜索,结果会很糟糕。所以问题中错误的偏移点可能是整个图像的质心。
现在我的函数看起来是这样的:
fvect2 findMeanShift(const PlainImage<uint8>& weights, const ImageRect& spatial_roi, fvect2 old_center, DebugOutput& debug)
{
const int w=weights.getWidth(), h=weights.getHeight();
int iter_count = 0;
fvect2 total_shift(0.0,0.0);
while(iter_count++ < 20)
{
fvect2 fTop(0,0);
float fBottom=0.0;
for(int y=std::max(spatial_roi.m_y, 0);y<std::min(h, spatial_roi.m_y+spatial_roi.m_height);++y)
for(int x=std::max(spatial_roi.m_x, 0);x<std::min(w, spatial_roi.m_x+spatial_roi.m_width);++x)
{
assert(y>=0 && x>=0 && y<h && x<w);
fvect2 cur_center(x, y);
float mult = weights.at(x, y)[0]/255.0;
fBottom += mult;
fTop += (cur_center-old_center) * mult;
}
fvect2 mean_shift = fTop/fBottom;
//LOGE("mean_shift: %.2f %.2f", mean_shift.x, mean_shift.y);
debug.addArrow(old_center, old_center+mean_shift);
old_center += mean_shift;
//LOGE("old_center: %.2f %.2f", old_center.x, old_center.y);
total_shift += mean_shift;
if(mean_shift.lengthF()<0.1)
break;
}
return total_shift;
}
我正在实施用于对象跟踪的 MeanShift 算法,使用来自此处的想法:http://www.cse.psu.edu/~rtc12/CSE598C/meanShiftColor.pdf
现在我有了后续帧的反投影图像。此类图像中的每个像素标记属于跟踪对象的概率:
上述来源中的 MeanShift 公式看起来是这样的:
w(xi) = 反投影图像中的像素。
x = 当前中心像素。
我不明白什么是spatial kernel
。
假设它可以是大小为 5x5 的二维高斯核,K(xi-x)*w(xi)可以用 pre-blurred 图像的像素替换。
我的代码看起来是这样的:
fvect2 findMeanShift(const PlainImage<uint8>& weights_smoothed, fvect2 old_center, DebugOutput& debug)
{
//LOGE("first center: %.2f %.2f", old_center.x, old_center.y);
const int w=weights_smoothed.getWidth(), h=weights_smoothed.getHeight();
int iter_count = 0;
fvect2 total_shift(0.0,0.0);
while(iter_count++ < 20)
{
fvect2 fTop(0,0);
float fBottom=0.0;
for(int y=0;y<h;++y)
for(int x=0;x<w;++x)
{
fvect2 cur_center(x, y);
float mult = weights_smoothed.at(x, y)[0]/255.0;
fBottom += mult;
fTop += (cur_center-old_center) * mult;
}
fvect2 mean_shift = fTop/fBottom;
//printf("mean_shift: %.2f %.2f", mean_shift.x, mean_shift.y);
debug.addArrow(old_center, old_center+mean_shift);
old_center += mean_shift;
//printf("old_center: %.2f %.2f", old_center.x, old_center.y);
total_shift += mean_shift;
if(mean_shift.lengthF()<0.1)
break;
}
return total_shift;
}
所以我只是通过平滑的反投影图像进行迭代,并且对于每个像素:
将其值添加到分母
将其值乘以从当前中心到分母的偏移。
第二次迭代收敛了,但是shift错了,不知道怎么debug。可能是公式实现的问题。
请用人类语言向我解释什么是空间核以及如何将其应用于权重图像。谢谢!
嗯,我明白了。空间掩码是搜索window。反向投影不需要模糊。应用于整个图像,1
在搜索内部 window,0
在外部。在this的第2页有更简单的解释。
如果在远离跟踪对象的地方搜索,结果会很糟糕。所以问题中错误的偏移点可能是整个图像的质心。
现在我的函数看起来是这样的:
fvect2 findMeanShift(const PlainImage<uint8>& weights, const ImageRect& spatial_roi, fvect2 old_center, DebugOutput& debug)
{
const int w=weights.getWidth(), h=weights.getHeight();
int iter_count = 0;
fvect2 total_shift(0.0,0.0);
while(iter_count++ < 20)
{
fvect2 fTop(0,0);
float fBottom=0.0;
for(int y=std::max(spatial_roi.m_y, 0);y<std::min(h, spatial_roi.m_y+spatial_roi.m_height);++y)
for(int x=std::max(spatial_roi.m_x, 0);x<std::min(w, spatial_roi.m_x+spatial_roi.m_width);++x)
{
assert(y>=0 && x>=0 && y<h && x<w);
fvect2 cur_center(x, y);
float mult = weights.at(x, y)[0]/255.0;
fBottom += mult;
fTop += (cur_center-old_center) * mult;
}
fvect2 mean_shift = fTop/fBottom;
//LOGE("mean_shift: %.2f %.2f", mean_shift.x, mean_shift.y);
debug.addArrow(old_center, old_center+mean_shift);
old_center += mean_shift;
//LOGE("old_center: %.2f %.2f", old_center.x, old_center.y);
total_shift += mean_shift;
if(mean_shift.lengthF()<0.1)
break;
}
return total_shift;
}