卡尔曼滤波预测三维坐标点

在网上找了很多卡尔曼滤波的代码,后来觉得文心一言生成的代码更简单容易理解。

修改了很多遍,勉强能运行,放在这里算是记录。

objectPoints是一个存储三维坐标点的矩阵,遍历矩阵预测更新坐标点。

卡尔曼滤波适用于线性系统,我试了几组数据发现偏差很大,后面溉用扩展卡尔曼滤波了。

// 添加第一个点 (X, Y, Z)  
objectPoints.push_back(cv::Point3f(0.378343f, 0.3473857f, 0.786856f)); // 原点  

// 添加第二个点  
objectPoints.push_back(cv::Point3f(-0.82075f, 0.9275763f, 0.748373f)); // X轴正方向上的一个单位点  

// 添加第三个点  
objectPoints.push_back(cv::Point3f(0.3775489f, -0.24635f, 0.8435f)); // Y轴正方向上的一个单位点  

// 添加第四个点  
objectPoints.push_back(cv::Point3f(-0.47589357f, -0.777578f, 0.3874f)); // Z轴正方向上的一个单位点(尽管在图像平面上Z通常为0)  

cout << "测试数据:" << objectPoints << endl;
int stateSize = 6; // 状态大小:位置(x, y) + 速度(vx, vy)  
int measureSize = 3; // 测量大小:位置(x, y)  
int controlSize = 0; // 没有控制输入 
cv::KalmanFilter kalmanFilter(stateSize, measureSize, controlSize, CV_32F);

// 设置初始状态  
cv::Mat initialState = Mat::zeros(stateSize, 1, CV_32F);
//initialState.setTo(cv::Scalar(0)); // 所有状态设置为0(位置在原点,速度为0)  
kalmanFilter.statePost = initialState;
// 转移矩阵 F  
// 假设dt是时间步长(例如,0.1秒)  
double dt = 0.1;
cv::Mat F = (cv::Mat_<float>(stateSize, stateSize) <<
				1, 0, dt, 0, 0, 0.5 * dt * dt,
				0, 1, 0, dt, 0, 0.5 * dt * dt,
				0, 0, 1, 0, dt, dt * dt,
				0, 0, 0, 1, 0, dt,
				0, 0, 0, 0, 1, 1,
				0, 0, 0, 0, 0, 1);
kalmanFilter.transitionMatrix = F;

// 测量矩阵 H  
cv::Mat H = (cv::Mat_<float>(measureSize, stateSize) <<
				1, 0, 0, 0, 0, 0,
				0, 1, 0, 0, 0, 0);
kalmanFilter.measurementMatrix = H;

// 过程噪声协方差矩阵 Q  
// 根据你的应用调整这些值  
cv::Mat Q = (cv::Mat_<float>(stateSize, stateSize) <<
				0.01, 0, 0, 0, 0, 0,
				0, 0.01, 0, 0, 0, 0,
				0, 0, 0.01, 0, 0, 0,
				0, 0, 0, 0.01, 0, 0,
				0, 0, 0, 0, 0.01, 0,
				0, 0, 0, 0, 0, 0.01);
kalmanFilter.processNoiseCov = Q;

// 测量噪声协方差矩阵 R  
// 根据你的测量设备的精度调整这些值  
cv::Mat R = (cv::Mat_<float>(measureSize, measureSize) <<
				0.01, 0,
				0, 0.01
				);
kalmanFilter.measurementNoiseCov = R;

 初始误差协方差矩阵 P  
 初始时可能不确定,所以设置为较大的值  
cv::Mat P = (cv::Mat_<float>(stateSize, stateSize) <<
				1, 0, 0, 0,
				0, 1, 0, 0,
				0, 0, 1, 0,
				0, 0, 0, 1
				) * 1e3;
kalmanFilter.errorCovPost = P;

// 用于存储预测的坐标点  
std::vector<cv::Point2f> predictedPoints;
// 准备测量值(仅位置,速度为0,因为卡尔曼滤波器将基于位置进行预测) 
for (size_t i = 0; i < objectPoints.size(); ++i)
{
				cv::Mat measurement = (cv::Mat_<float>(measureSize, 1) << objectPoints[i].x, objectPoints[i].y,0);
				
				// 预测  
				cv::Mat prediction = kalmanFilter.predict();
				cout <<"prediction" << prediction << endl;
				//计算测量值
				measurement.at<float>(0) = (float)objectPoints[i].x;
				measurement.at<float>(1) = (float)objectPoints[i].y;
				cout << "measurement" <<measurement.at<float>(0) << "\t" << measurement.at<float>(1)<< endl;
				// 校正(使用当前测量值)  
				kalmanFilter.correct(measurement);
				
				// 现在kalmanFilter.statePost包含校正后的状态估计(位置和速度)  
				// 提取位置信息  
				float predictedX = kalmanFilter.statePost.at<float>(0);
				float predictedY = kalmanFilter.statePost.at<float>(1);
				cout << "xxxx" << predictedX << "yyyy" << predictedY << endl;
				predictedPoints.push_back(cv::Point2f(predictedX, predictedY));
				// 确保预测的位置在图像范围内  
				predictedX = std::max(0.0f, std::min(predictedX, copy.cols - 1.0f));
				predictedY = std::max(0.0f, std::min(predictedY, copy.rows - 1.0f));
				// 在图像上绘制点  
				// 存储预测的坐标点以供后续绘制  
}
// 在图像上绘制一系列的点以显示轨迹  
for (const auto& point : predictedPoints)
{
				cv::circle(copy, point, 5, cv::Scalar(0, 255, 255), -1); // 黄色圆点,-1表示填充  
				std::cout << "Predicted point: (" << point.x << ", " << point.y << ")" << std::endl;
}

objectPoints.clear();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值