C++ Meanshift目标跟踪算法研究搜索窗口质心更新问题

C++ Meanshift目标跟踪算法研究搜索窗口质心更新问题,c++,opencv,video-tracking,mean-shift,C++,Opencv,Video Tracking,Mean Shift,我一直在尝试实现用于跟踪对象的meanshift算法,并介绍了相关概念 根据现在,我已经成功地从我的相机生成了一个反向投影流,带有一个单通道色调roi直方图和一个单通道色调视频流,看起来不错,我知道opencv库中有一个meanshift函数,但我正在尝试使用opencv中提供的数据结构实现一个,计算矩并计算搜索窗口的平均质心 但由于某种原因,我无法在代码中找到问题所在,因为它会不断收敛到视频流的左上角,以便跟踪任何输入roi(感兴趣区域)。以下是用于计算搜索窗口质心的函数的代码片段,我觉得问题

我一直在尝试实现用于跟踪对象的meanshift算法,并介绍了相关概念

根据现在,我已经成功地从我的相机生成了一个反向投影流,带有一个单通道色调roi直方图和一个单通道色调视频流,看起来不错,我知道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;
    }
}
无效时刻(Mat和backproj、Rect和win){
int x_c,y_c,x_c_new,y_c_new;
int idx_行,idx_列;
双m00=0.0,m01=0.0,m10=0.0;
双res=1.0,TOL=0.003;
//将搜索窗口的中心设置为概率图像的中心:
y_c=(int)backproj.rows/2;
x_c=(int)backproj.cols/2;
//质心搜索解算器,直到残差低于特定公差:
while(res>TOL){
win.width=(int)80;
win.height=(int)60;
//位于搜索窗口“左下角”位置(x,y)的第一个数组元素:
win.x=(int)(x_c-win.width/2);
win.y=(int)(y_c-win.height/2);
//模校正,因为负整数的模在C中为负:
如果(赢x<0)
win.x=win.x%backproj.cols+backproj.cols;
如果(赢y<0)
win.y=win.y%backproj.rows+backproj.rows;
对于(int i=0;i
这是我第二次询问stackoverflow,所以请原谅我忘记遵守的任何指导原则

编辑

由于Daniel Strul指出,将m00、m01、m10更改为在WHILE-LOOP中阻止级别变量,而不是函数级别变量,但问题仍然存在。现在,搜索窗口围绕帧边界跳跃,而不是聚焦于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;
    }
}
无效时刻(Mat和backproj、Rect和win){
int x_c,y_c,x_c_new,y_c_new;
int idx_行,idx_列;
双m00、m01、m10;
双res=1.0,TOL=0.003;
//将搜索窗口的中心设置为概率图像的中心:
y_c=(int)backproj.rows/2;
x_c=(int)backproj.cols/2;
//质心搜索解算器,直到残差低于特定公差:
while(res>TOL){
m00=0.0,m01=0.0,m10=0.0
win.width=(int)80;
win.height=(int)60;
//位于搜索窗口“左下角”位置(x,y)的第一个数组元素:
win.x=(int)(x_c-win.width/2);
win.y=(int)(y_c-win.height/2);
//模校正,因为负整数的模在C中为负:
如果(赢x<0)
win.x=win.x%backproj.cols+backproj.cols;
如果(赢y<0)
win.y=win.y%backproj.rows+backproj.rows;
对于(int i=0;i
算法总是收敛到左上角,与输入数据无关的原因是
m00
m10
m01
从不重置为零:

  • 在迭代0中,对于每个力矩变量
    m00
    m10
    while (res > TOL){
        ...
        double m00 = 0.0, m01 = 0.0, m10 = 0.0;
        for (int i = 0; i < win.height; i++ ){
            ...
    
        x_c_new = win.x + (int) ( m10 / m00 ) ;
        y_c_new = win.y + (int) ( m01 / m00 );