C++ C++/用于视频稳定的OpenCV-Kalman滤波器
我尝试用卡尔曼滤波器来稳定视频,使其平滑。但是我有一些问题 每次,我有两个帧:一个是当前帧,另一个是当前帧。 以下是我的工作流程:C++ C++/用于视频稳定的OpenCV-Kalman滤波器,c++,opencv,video,kalman-filter,C++,Opencv,Video,Kalman Filter,我尝试用卡尔曼滤波器来稳定视频,使其平滑。但是我有一些问题 每次,我有两个帧:一个是当前帧,另一个是当前帧。 以下是我的工作流程: 计算goodFeaturesToTrack() 使用calcOpticalFlowPyrLK()计算光流 只保留好的观点 估计刚性变换 卡尔曼滤波平滑 扭曲图片 但我认为Kalman有点问题,因为最后我的视频仍然不稳定,一点也不平滑,甚至比原来的更糟 这是我的Kalman代码 void StabilizationTestSimple2::init_kalman(
- 计算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));
}
void StabilizationTestSimple2::init_kalman(双x,双y)
{
KF.statePre.at(0)=x;
KF.statePre.at(1)=y;
KF.statePre.at(2)=0;
KF.statePre.at(3)=0;
KF.transitionMatrix=*(Mat_u4,4)KF.transitionMatrix=*(Mat_4,4)谢谢你的回答。实际上在做这件事之前,我不知道卡尔曼滤波器,所以我试着读了一些关于它的文章,现在我知道了它的工作原理。但这是真的,尽管我知道它是如何工作的,但我真的不知道如何为我的问题设置我自己的参数,因此我没有真正知道。我想我使用的是像素d不是米。那么我的视频的帧速率大约是25-27fps。但是是的,如果你能解释一下你是如何设置processNoisCov、setIdentity和measurementNoiseCov的,它可以帮我很多忙。提前谢谢你!@lilouch:补充了更多。谢谢你的回答。这在我的头脑中变得更清晰了,但仍然有些不理解。实际上我想估计两帧之间的变换(由EstimaterialDigTransform()得到),这就是为什么我不想预测速度。实际上我想预测x,y和teta,但我不知道如何将θ放在我的系统中,这就是为什么我没有将它放在我的系统中(错误)。这只是一个有3行和3列(x,y,theta)的变换矩阵吗否则,如果我没有速度,怎么能“预测”所有协方差矩阵?仅仅通过“猜测”?你所说的“测量中的加性协方差noisecov是每帧相加的,所以请记住所表示的变化超过1/25秒”是什么意思在我的过程中,我必须为每一帧添加一个术语?非常感谢。您的测量值是z=H*x
,或者用您的术语meas=measurementMatrix*statePost
。现在您正在将measurementMatrix
设置为identity,这意味着您测量您的状态变量。如果您只能测量positi在上,您的矩阵应该是非正方形的:[[1 0 0],[0 1 0]]
这样它会产生一个测量值[x y]'
您的测量值noisecov
将仅为2x2。
/// 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);
}
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));