Алгоритм среднего смещения для отслеживания проблемы выдачи объектов, обновление центроида окна поиска

Я пытался реализовать алгоритм смещения средств для отслеживания объектов и прошел через концепции.

На данный момент мне удалось успешно сгенерировать обратный проецируемый поток из моей камеры с помощью одноканальной гистограммы оттенка Роя и одноканального видеопотока оттенка, что выглядит хорошо, я знаю, что в библиотеке opencv есть функция смещения средств, но я пытаюсь реализовать один сам, используя структуры данных, предоставленные в 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 вместо переменных уровня функции, спасибо Дэниелу Струлю за указание на это, но проблема все еще остается. Теперь окно поиска прыгает вокруг границ кадра, а не фокусируется на 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;
}
}

4

Решение

Причина, по которой ваши алгоритмы всегда сходятся к верхнему левому углу независимо от входных данных, заключается в том, что m00, m10 а также m01 никогда не обнуляются:

  • На итерации 0 для каждой переменной момента m00, m10 а также m01Вы вычисляете правильное значение m0
  • Между итерацией 0 и итерацией 1 переменные моментов не сбрасываются и сохраняют свое прежнее значение
  • Таким образом, на итерации 1 для каждой переменной момента m00, m10 а также m01вы фактически суммируете новый момент со старым и получаете (м0 + м1 )
  • На итерации 2 вы продолжаете суммировать новые моменты поверх предыдущих и получаете (m0 + м1 + м2 )
  • И так далее, итерация за итерацией.

По крайней мере, переменные момента должны быть сброшены в начале каждой итерации.

В идеале они не должны быть переменными уровня функции, а должны быть переменными уровня блока, так как они не используются вне итераций цикла (кроме как для целей отладки):

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 );
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]