#include <iostream>
|
#include <fstream>
|
#include <sstream>
|
#include <vector>
|
#include <regex>
|
#include <cmath>
|
#include <limits>
|
|
using namespace std;
|
|
// 定义一个结构体来保存每一行的值
|
struct TargetData {
|
int id;
|
double x, y, width, height;
|
};
|
|
// 读取日志文件并提取目标数据
|
vector<TargetData> readLogFile(const string& filepath) {
|
vector<TargetData> data;
|
ifstream file(filepath);
|
string line;
|
|
// 正则表达式来匹配Target ID后的五个值
|
regex targetRegex("Target ID: (-?\\d+),\\s*(-?\\d+),\\s*(-?\\d+),\\s*(-?\\d+),\\s*(-?\\d+)");
|
|
while (getline(file, line)) {
|
smatch matches;
|
if (regex_search(line, matches, targetRegex)) {
|
TargetData target;
|
target.id = stoi(matches[1].str());
|
target.x = stod(matches[2].str());
|
target.y = stod(matches[3].str());
|
target.width = stod(matches[4].str());
|
target.height = stod(matches[5].str());
|
|
data.push_back(target);
|
}
|
}
|
return data;
|
}
|
|
// 清洗数据,去掉横坐标小于100或大于600的数据,以及极端值
|
void cleanData(vector<TargetData>& data, double n) {
|
// 计算平均值
|
double sum = 0;
|
for (const auto& target : data) {
|
sum += target.width;
|
}
|
double mean = sum / data.size();
|
|
// 计算标准差
|
double variance = 0;
|
for (const auto& target : data) {
|
variance += pow(target.width - mean, 2);
|
}
|
double stddev = sqrt(variance / data.size());
|
|
// 根据误差系数范围n清洗数据
|
vector<TargetData> cleanedData;
|
for (const auto& target : data) {
|
// 添加条件,去掉横坐标小于100或大于600的数据
|
if (target.x >= 100 && target.x <= 600 &&
|
abs(target.width - mean) <= n * stddev) {
|
cleanedData.push_back(target);
|
}
|
}
|
|
data = cleanedData;
|
}
|
|
// 用最小二乘法来计算线性回归的参数 (width = a * y + b)
|
void fitLinearModel(const vector<TargetData>& data, double& a, double& b) {
|
int n = data.size();
|
double sum_y = 0, sum_width = 0, sum_yy = 0, sum_yw = 0;
|
|
// 计算所需的累加和
|
for (const auto& target : data) {
|
sum_y += target.y;
|
sum_width += target.width;
|
sum_yy += target.y * target.y;
|
sum_yw += target.y * target.width;
|
}
|
|
// 计算线性回归的系数 a 和 b
|
double denominator = n * sum_yy - sum_y * sum_y;
|
if (denominator == 0) {
|
a = 0;
|
b = 0;
|
return;
|
}
|
|
a = (n * sum_yw - sum_y * sum_width) / denominator;
|
b = (sum_yy * sum_width - sum_y * sum_yw) / denominator;
|
}
|
|
// 输出拟合结果
|
void printFitEquation(double a, double b) {
|
cout << "拟合结果: width = " << a << " * y + " << b << endl;
|
}
|
|
// 打印data中的所有数据
|
void printData(const vector<TargetData>& data) {
|
for (const auto& target : data) {
|
cout << "ID: " << target.id
|
<< ", x: " << target.x
|
<< ", y: " << target.y
|
<< ", width: " << target.width
|
<< ", height: " << target.height << endl;
|
}
|
}
|
|
|
int main(int argc, char* argv[]) {
|
if (argc < 3) {
|
cout << "使用方法: " << argv[0] << " <日志文件路径> <误差系数范围>" << endl;
|
return 1;
|
}
|
|
string logFilePath = argv[1];
|
double n = stod(argv[2]); // 误差系数范围
|
|
// 读取日志文件中的目标数据
|
vector<TargetData> data = readLogFile(logFilePath);
|
|
// 数据清洗
|
cleanData(data, n);
|
|
// 打印清洗后的数据
|
cout << "\n清洗后的数据:" << endl;
|
printData(data);
|
|
// 使用最小二乘法拟合数据
|
double a, b;
|
fitLinearModel(data, a, b);
|
|
// 输出拟合的函数公式
|
printFitEquation(a, b);
|
|
return 0;
|
}
|