gpt4 book ai didi

c++ - 跟踪目标问题的均值漂移算法计算搜索窗口的质心更新

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:16:24 26 4
gpt4 key购买 nike

我一直在尝试实现用于跟踪对象的均值偏移算法,并且已经了解了所涉及的概念。

到目前为止,我已经成功地从我的相机生成了一个带有单 channel 色调 roi 直方图和单 channel 色调视频流的反向投影流,这看起来不错,我知道 opencv 库中有一个 meanshift 函数,但我尝试使用 opencv 中提供的数据结构自己实现一个,计算矩并计算搜索窗口的平均质心。

但出于某种原因,我无法在我的代码中找到问题,因为它一直会聚到我的视频流的左上角,以便跟踪任何输入 roi(感兴趣区域)。以下是计算搜索窗口质心的函数代码片段,我觉得问题出在哪里但不确定是什么,如果有人能指出正确的方向,我将不胜感激:

void moment(Mat &backproj, Rect &win){

int x_c, y_c, x_c_new, y_c_new;
int idx_row, idx_col;
double m00 = 0.0 , m01 = 0.0 , m10 = 0.0 ;
double res = 1.0, TOL = 0.003 ;

//Set the center of search window as the center of the probabilistic image:
y_c = (int) backproj.rows / 2 ;
x_c = (int) backproj.cols / 2 ;

//Centroid search solver until residual below certain tolerance:
while (res > TOL){

win.width = (int) 80;
win.height = (int) 60;

//First array element at position (x,y) "lower left corner" of the search window:
win.x = (int) (x_c - win.width / 2) ;
win.y = (int) (y_c - win.height / 2);

//Modulo correction since modulo of negative integer is negative in C:
if (win.x < 0)
win.x = win.x % backproj.cols + backproj.cols ;

if (win.y < 0)
win.y = win.y % backproj.rows + backproj.rows ;

for (int i = 0; i < win.height; i++ ){

//Traverse along y-axis (height) i.e. rows ensuring wrap around top/bottom boundaries:
idx_row = (win.y + i) % (int)backproj.rows ;

for (int j = 0; j < win.width; j++ ){

//Traverse along x-axis (width) i.e. cols ensuring wrap around left/right boundaries:
idx_col = (win.x + j) % (int)backproj.cols ;
//Compute Moments:
m00 += (double) backproj.at<uchar>(idx_row, idx_col) ;
m10 += (double) backproj.at<uchar>(idx_row, idx_col) * i ;
m01 += (double) backproj.at<uchar>(idx_row, idx_col) * j ;
}
}

//Compute new centroid coordinates of the search window:
x_c_new = (int) ( m10 / m00 ) ;
y_c_new = (int) ( m01 / m00 );

//Compute the residual:
res = sqrt( pow((x_c_new - x_c), 2.0) + pow((y_c_new - y_c), 2.0) ) ;

//Set new search window centroid coordinates:
x_c = x_c_new;
y_c = y_c_new;
}
}

这是我第二次在 stackoverflow 上查询,所以请原谅我忘记遵循的任何准则。

编辑

将 m00 、 m01 、 m10 更改为 WHILE-LOOP 中的 block 级变量而不是函数级变量,感谢 Daniel Strul 指出,但问题仍然存在。现在,搜索窗口会围绕帧边界跳转,而不是关注 roi。

    void moment(Mat &backproj, Rect &win){

int x_c, y_c, x_c_new, y_c_new;
int idx_row, idx_col;
double m00 , m01 , m10 ;
double res = 1.0, TOL = 0.003 ;

//Set the center of search window as the center of the probabilistic image:
y_c = (int) backproj.rows / 2 ;
x_c = (int) backproj.cols / 2 ;

//Centroid search solver until residual below certain tolerance:
while (res > TOL){

m00 = 0.0 , m01 = 0.0 , m10 = 0.0
win.width = (int) 80;
win.height = (int) 60;

//First array element at position (x,y) "lower left corner" of the search window:
win.x = (int) (x_c - win.width / 2) ;
win.y = (int) (y_c - win.height / 2);

//Modulo correction since modulo of negative integer is negative in C:
if (win.x < 0)
win.x = win.x % backproj.cols + backproj.cols ;

if (win.y < 0)
win.y = win.y % backproj.rows + backproj.rows ;

for (int i = 0; i < win.height; i++ ){

//Traverse along y-axis (height) i.e. rows ensuring wrap around top/bottom boundaries:
idx_row = (win.y + i) % (int)backproj.rows ;

for (int j = 0; j < win.width; j++ ){

//Traverse along x-axis (width) i.e. cols ensuring wrap around left/right boundaries:
idx_col = (win.x + j) % (int)backproj.cols ;
//Compute Moments:
m00 += (double) backproj.at<uchar>(idx_row, idx_col) ;
m10 += (double) backproj.at<uchar>(idx_row, idx_col) * i ;
m01 += (double) backproj.at<uchar>(idx_row, idx_col) * j ;
}
}

//Compute new centroid coordinates of the search window:
x_c_new = (int) ( m10 / m00 ) ;
y_c_new = (int) ( m01 / m00 );

//Compute the residual:
res = sqrt( pow((x_c_new - x_c), 2.0) + pow((y_c_new - y_c), 2.0) ) ;

//Set new search window centroid coordinates:
x_c = x_c_new;
y_c = y_c_new;
}
}

最佳答案

你的算法总是独立于输入数据收敛到左上角的原因是 m00 , m10m01永远不会重置为零:

  • 在第 0 次迭代中,对于每个矩变量 m00 , m10m01 ,你计算出正确的值 m0
  • 在第 0 次迭代和第 1 次迭代之间,moments 变量不会被重置并保持其先前的值
  • 因此,在第 1 次迭代中,对于每个矩变量 m00 , m10m01 ,您实际上将新时刻与旧时刻相加并获得 ( m0 + m1 )
  • 在第 2 次迭代中,您继续在先前的时刻之上对新时刻求和并获得 ( m0 + m1 + m2 )
  • 以此类推,逐次迭代。

至少,时刻变量应该在每次迭代开始时重置。

理想情况下,它们不应该是函数级变量,而应该是 block 级变量,因为它们在循环迭代之外没有用处(调试目的除外):

while (res > TOL){
...
double m00 = 0.0, m01 = 0.0, m10 = 0.0;
for (int i = 0; i < win.height; i++ ){
...

编辑 1

您遇到的第二个问题(ROI 到处跳跃)的原因是力矩的计算是基于相对坐标 i 的。和 j .

因此,您计算的是 [ avg(j) , avg(i) ],而您真正想要的是 [ avg(y) , avg(x) ]。为了解决这个问题,我提出了第一个解决方案。我将其替换为下面的更简单的解决方案。

编辑 2最简单的解决方案是在每次迭代结束时添加 ROI 角的坐标:

    x_c_new = win.x + (int) ( m10 / m00 ) ;
y_c_new = win.y + (int) ( m01 / m00 );

关于c++ - 跟踪目标问题的均值漂移算法计算搜索窗口的质心更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33355477/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com