C ++ / OpenCV — фильтр Калмана для стабилизации видео

Я пытаюсь стабилизировать видео с помощью фильтра Калмана для сглаживания. Но у меня есть некоторые проблемы

Каждый раз у меня есть два кадра: один текущий и другой.
Вот мой рабочий процесс:

  • Вычислить goodFeaturesToTrack ()
  • Вычислить оптический поток с помощью calcOpticalFlowPyrLK ()
  • Держите только хорошие очки
  • Оцените жесткую трансформацию
  • Сглаживание с использованием фильтра Калмана
  • Деформация картины.

Но я думаю, что с Калманом что-то не так, потому что в конце мое видео все еще не стабилизировано и совсем не гладкое, оно даже хуже оригинала …

Вот мой код Кальмана

void StabilizationTestSimple2::init_kalman(double x, double y)
{

KF.statePre.at<float>(0) = x;
KF.statePre.at<float>(1) = y;
KF.statePre.at<float>(2) = 0;
KF.statePre.at<float>(3) = 0;

KF.transitionMatrix = *(Mat_<float>(4,4) << 1,0,1,0,    0,1,0,1,     0,0,1,0,   0,0,0,1);
KF.processNoiseCov = *(Mat_<float>(4,4) << 0.2,0,0.2,0,  0,0.2,0,0.2,  0,0,0.3,0,
0,0,0,0.3);
setIdentity(KF.measurementMatrix);
setIdentity(KF.processNoiseCov,Scalar::all(1e-6));
setIdentity(KF.measurementNoiseCov,Scalar::all(1e-1));
setIdentity(KF.errorCovPost, Scalar::all(.1));
}

и вот как я это использую. Я ставлю только интересную часть. Весь этот код находится внутри цикла flor.
cornerPrev2 и cornerCurr2 содержит все характерные точки, обнаруженные непосредственно перед (с помощью calcOpticalFlowPyrLK ())

    /// Transformation
Mat transformMatrix = estimateRigidTransform(cornersPrev2,cornersCurr2 ,false);

// in rare cases no transform is found. We'll just use the last known good transform.
if(transformMatrix.data == NULL) {
last_transformationmatrix.copyTo(transformMatrix);
}

transformMatrix.copyTo(last_transformationmatrix);

// decompose T
double dx = transformMatrix.at<double>(0,2);
double dy = transformMatrix.at<double>(1,2);
double da = atan2(transformMatrix.at<double>(1,0), transformMatrix.at<double>(0,0));

// Accumulated frame to frame transform
x += dx;
y += dy;
a += da;
std::cout << "accumulated x,y: (" << x << "," << y << ")" << endl;

if (compteur==0){
init_kalman(x,y);
}
else {vector<Point2f> smooth_feature_point;
Point2f smooth_feature=kalman_predict_correct(x,y);
smooth_feature_point.push_back(smooth_feature);
std::cout << "smooth x,y: (" << smooth_feature.x << "," << smooth_feature.y << ")" << endl;

// target - current
double diff_x = smooth_feature.x - x;//
double diff_y = smooth_feature.y - y;

dx = dx + diff_x;
dy = dy + diff_y;

transformMatrix.at<double>(0,0) = cos(da);
transformMatrix.at<double>(0,1) = -sin(da);
transformMatrix.at<double>(1,0) = sin(da);
transformMatrix.at<double>(1,1) = cos(da);
transformMatrix.at<double>(0,2) = dx;
transformMatrix.at<double>(1,2) = dy;

warpAffine(currFrame,outImg,transformMatrix,prevFrame.size(), INTER_NEAREST|WARP_INVERSE_MAP, BORDER_CONSTANT);

namedWindow("stabilized");
imshow("stabilized",outImg);
namedWindow("Original");
imshow("Original",originalFrame);}

Может у кого-то есть идея, почему она не работает?

Поблагодарить

4

Решение

KF.transitionMatrix = *(Mat_<float>(4,4) << 1,0,1,0,    0,1,0,1,     0,0,1,0,   0,0,0,1);
KF.processNoiseCov = *(Mat_<float>(4,4) << 0.2,0,0.2,0,  0,0.2,0,0.2,  0,0,0.3,0,
0,0,0,0.3);
setIdentity(KF.measurementMatrix);
setIdentity(KF.processNoiseCov,Scalar::all(1e-6));
setIdentity(KF.measurementNoiseCov,Scalar::all(1e-1));
setIdentity(KF.errorCovPost, Scalar::all(.1));

Ваш processNoiseCov не является симметричным, и я сомневаюсь, что у вас есть правильные недиагональные члены. Я бы придерживался там диагональной матрицы, пока ты не поймешь KF лучше.

С другой стороны, вы, кажется, немедленно перезаписываете это setIdentity с крошечными значениями, что, вероятно, является ошибкой. Может быть, вы добавили это после проблем с неверной матрицей выше?

Если вы опишите частоту кадров и единицы вашего состояния (метры? Пиксели?), Мы можем поговорить о том, как выбрать хорошие значения для processNoiseCov а также measurementNoiseCov,

РЕДАКТИРОВАТЬ:

Хорошо, учитывая, что ваше состояние [ x_pixels, y_pixels, dx_pixels, dy_pixels ] Вот несколько советов:

  • Ваша измерительная матрица I таким образом, вы говорите, что измеряете те же самые вещи, что и в вашем состоянии (это несколько необычно: часто вы измеряете только некоторое подмножество вашего состояния, например, у вас не будет оценки скорости в ваших измерениях).
  • Учитывая, что ваша измерительная матрица I значение processNoiseCov а также measurementNoiseCov похожи, так что я буду обсуждать их вместе. Ваш processNoiseCov должна быть диагональная матрица, где каждый член является дисперсия (квадрат стандартного отклонения) того, как эти значения могут меняться между кадрами. Например, если есть вероятность 68% (см. нормальное распределение) что ваши пиксельные смещения находятся в пределах 100 пикселей в каждом кадре, диагональная запись для позиции должна быть 100 * 100 = 10000 (помните, дисперсия в квадрате стандартного ввода). Вы должны сделать аналогичную оценку того, как изменится скорость. (Дополнительно: должны присутствовать ко-меняющиеся (недиагональные) термины, потому что изменение скорости связано с изменением положения, но вы можете обойтись без этого, пока это не будет иметь смысла для вас. Я объяснил это в других ответах).
  • Ваша аддитивная ковариация в processNoiseCov добавляется каждый Рамка так что имейте ввиду, что представленные изменения составляют более 1/25 секунды.
  • Ваш measurementNoiseCov имеет такие же единицы измерения (опять же, матрица измерений идентична), но должна отражать, насколько точны ваши измерения по сравнению с непознаваемыми фактическими истинными значениями.
  • Часто вы можете измерить фактические значения для вашего процесса и измерений и вычислить их фактическую ковариацию (в Excel, Python или Matlab или что-то еще).
  • Ваш errorCovPost это ваша первоначальная неопределенность, выраженная точно так же, как ваша аддитивная ковариация для каждого кадра, но это описание того, насколько вы уверены в правильности вашего начального состояния.
  • Правильно получить эти ковариационные матрицы самая важная вещь при использовании KF. При разработке KF вы всегда будете тратить больше времени на то, чтобы сделать это правильно, чем делать что-либо еще.
2

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


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