wangrong
2025-03-19 291afb9c81aae1d15d9e3edcea618d0a2e1fc5a6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#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;
}