From 871969df9349c83b1d85316c74378bef14c6e9e8 Mon Sep 17 00:00:00 2001 From: ybnfsh <2329959058@qq.com> Date: Sun, 28 Sep 2025 10:15:11 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=80=89=E9=A2=98?= =?UTF-8?q?=E5=B9=B6=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driverless_car_yb/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/driverless_car_yb/README.md diff --git a/src/driverless_car_yb/README.md b/src/driverless_car_yb/README.md new file mode 100644 index 0000000000..8c27ba2124 --- /dev/null +++ b/src/driverless_car_yb/README.md @@ -0,0 +1 @@ +无人车 \ No newline at end of file From 2897bfcf078a7baf6322dfa96496d2bb969a6dde Mon Sep 17 00:00:00 2001 From: ybnfsh <2329959058@qq.com> Date: Mon, 17 Nov 2025 10:23:24 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E6=97=A0=E4=BA=BA=E8=BD=A6=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E5=9F=BA=E4=BA=8E=E5=8E=86=E5=8F=B2=E4=BC=A0=E6=84=9F?= =?UTF-8?q?=E5=99=A8=E6=95=B0=E6=8D=AE=E9=A2=84=E6=B5=8B=E6=9C=AA=E6=9D=A5?= =?UTF-8?q?=E8=BF=90=E5=8A=A8=E7=8A=B6=E6=80=81=E7=9A=84=E5=9C=BA=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driverless_car_yb/main_speed.py | 161 ++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 src/driverless_car_yb/main_speed.py diff --git a/src/driverless_car_yb/main_speed.py b/src/driverless_car_yb/main_speed.py new file mode 100644 index 0000000000..3afff2cae4 --- /dev/null +++ b/src/driverless_car_yb/main_speed.py @@ -0,0 +1,161 @@ +import torch +import torch.nn as nn +import torch.optim as optim +import numpy as np +import pandas as pd +from sklearn.model_selection import train_test_split +from sklearn.preprocessing import StandardScaler +import matplotlib.pyplot as plt + +# 设置随机种子,保证结果可复现 +torch.manual_seed(42) +np.random.seed(42) + + +class SpeedPredictor(nn.Module): + """无人车速度预测模型:使用LSTM处理时序数据""" + def __init__(self, input_size, hidden_size, num_layers, output_size=1): + super(SpeedPredictor, self).__init__() + self.lstm = nn.LSTM( + input_size=input_size, # 输入特征数(如速度、加速度、方向盘角度等) + hidden_size=hidden_size, # LSTM隐藏层大小 + num_layers=num_layers, # LSTM层数 + batch_first=True # 输入格式为(batch, seq_len, input_size) + ) + self.fc = nn.Linear(hidden_size, output_size) # 输出层(预测未来速度) + + def forward(self, x): + # x shape: (batch_size, seq_len, input_size) + lstm_out, _ = self.lstm(x) # lstm_out shape: (batch_size, seq_len, hidden_size) + # 取最后一个时间步的输出用于预测 + last_out = lstm_out[:, -1, :] # shape: (batch_size, hidden_size) + pred = self.fc(last_out) # shape: (batch_size, output_size) + return pred + + +def create_sequences(data, seq_len, pred_len=1): + """ + 将时序数据转换为输入序列和标签 + data: 原始数据(特征矩阵) + seq_len: 输入序列长度(用过去多少个时间步预测未来) + pred_len: 预测未来多少个时间步(这里简化为1) + """ + xs, ys = [], [] + for i in range(len(data) - seq_len - pred_len + 1): + x = data[i:(i + seq_len)] # 输入序列(过去seq_len个时间步的特征) + y = data[i + seq_len:i + seq_len + pred_len, 0] # 标签(未来1个时间步的速度,假设第0列是速度) + xs.append(x) + ys.append(y) + return np.array(xs), np.array(ys) + + +def main(): + # 1. 数据准备(这里使用模拟数据,实际应用中替换为真实传感器数据) + # 模拟特征:[速度(m/s), 加速度(m/s²), 方向盘角度(°), 油门开度(%), 刹车压力(bar)] + num_samples = 10000 + time = np.linspace(0, 100, num_samples) + speed = 10 + 5 * np.sin(time) + np.random.normal(0, 0.5, num_samples) # 带噪声的正弦曲线模拟速度 + acceleration = np.gradient(speed, time) # 加速度(速度的导数) + steering = 10 * np.sin(time/2) + np.random.normal(0, 1, num_samples) # 方向盘角度 + throttle = 30 + 10 * np.sin(time/3) + np.random.normal(0, 2, num_samples) # 油门开度 + brake = np.where(speed < 8, 5 + np.random.normal(0, 1, num_samples), np.random.normal(0, 0.5, num_samples)) # 刹车压力 + + # 组合成特征矩阵 + data = np.column_stack([speed, acceleration, steering, throttle, brake]) + + # 2. 数据预处理 + scaler = StandardScaler() # 标准化(均值为0,方差为1) + data_scaled = scaler.fit_transform(data) + + # 创建序列数据(用过去10个时间步预测未来1个时间步的速度) + seq_len = 10 + X, y = create_sequences(data_scaled, seq_len) + + # 划分训练集和测试集 + X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False) # 时序数据不打乱顺序 + + # 转换为PyTorch张量 + X_train = torch.FloatTensor(X_train) + y_train = torch.FloatTensor(y_train) + X_test = torch.FloatTensor(X_test) + y_test = torch.FloatTensor(y_test) + + # 3. 模型初始化 + input_size = X_train.shape[2] # 特征数(这里是5) + hidden_size = 64 + num_layers = 2 + model = SpeedPredictor(input_size, hidden_size, num_layers) + + # 4. 定义损失函数和优化器 + criterion = nn.MSELoss() # 均方误差损失(回归任务) + optimizer = optim.Adam(model.parameters(), lr=0.001) + + # 5. 模型训练 + epochs = 50 + batch_size = 32 + train_losses = [] + test_losses = [] + + for epoch in range(epochs): + model.train() # 训练模式 + epoch_loss = 0 + # 分批训练 + for i in range(0, len(X_train), batch_size): + batch_X = X_train[i:i+batch_size] + batch_y = y_train[i:i+batch_size] + + optimizer.zero_grad() # 清零梯度 + outputs = model(batch_X) + loss = criterion(outputs, batch_y) + loss.backward() # 反向传播 + optimizer.step() # 更新参数 + + epoch_loss += loss.item() * batch_X.size(0) # 累计损失 + + train_loss = epoch_loss / len(X_train) + train_losses.append(train_loss) + + # 测试集验证 + model.eval() # 评估模式 + with torch.no_grad(): + y_pred = model(X_test) + test_loss = criterion(y_pred, y_test).item() + test_losses.append(test_loss) + + if (epoch + 1) % 5 == 0: + print(f'Epoch [{epoch+1}/{epochs}], Train Loss: {train_loss:.6f}, Test Loss: {test_loss:.6f}') + + # 6. 结果可视化 + # 反标准化(将预测结果转换为原始速度尺度) + # 构造反标准化需要的虚拟特征矩阵(仅用于恢复速度的尺度) + dummy = np.zeros_like(data_scaled[:len(y_test)]) + dummy[:, 0] = y_test.numpy().flatten() # 测试集真实速度(标准化后) + y_test_original = scaler.inverse_transform(dummy)[:, 0] # 原始尺度真实速度 + + dummy_pred = np.zeros_like(data_scaled[:len(y_test)]) + dummy_pred[:, 0] = y_pred.numpy().flatten() # 预测速度(标准化后) + y_pred_original = scaler.inverse_transform(dummy_pred)[:, 0] # 原始尺度预测速度 + + # 绘制预测 vs 真实值 + plt.figure(figsize=(12, 6)) + plt.plot(y_test_original, label='真实速度', alpha=0.7) + plt.plot(y_pred_original, label='预测速度', alpha=0.7) + plt.xlabel('时间步') + plt.ylabel('速度 (m/s)') + plt.title('无人车速度预测结果') + plt.legend() + plt.show() + + # 绘制损失曲线 + plt.figure(figsize=(12, 6)) + plt.plot(train_losses, label='训练损失') + plt.plot(test_losses, label='测试损失') + plt.xlabel('Epoch') + plt.ylabel('MSE损失') + plt.title('训练与测试损失曲线') + plt.legend() + plt.show() + + +if __name__ == '__main__': + main() \ No newline at end of file From 507c6736a4449c0b60ae6562da77d3b046d6f2cd Mon Sep 17 00:00:00 2001 From: ybnfsh <2329959058@qq.com> Date: Mon, 24 Nov 2025 09:22:23 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=80=89=E9=A2=98?= =?UTF-8?q?=E5=B9=B6=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driverless _car_yb/main.direction.py | 275 +++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 src/driverless _car_yb/main.direction.py diff --git a/src/driverless _car_yb/main.direction.py b/src/driverless _car_yb/main.direction.py new file mode 100644 index 0000000000..efc22d79eb --- /dev/null +++ b/src/driverless _car_yb/main.direction.py @@ -0,0 +1,275 @@ +import os +import cv2 +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt +from sklearn.model_selection import train_test_split +from tensorflow.keras.models import Sequential, load_model +from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, Lambda +from tensorflow.keras.optimizers import Adam +from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping + + +# -------------------------- +# 1. 数据生成与预处理 +# -------------------------- +def create_simulated_data(data_dir, num_samples=1000): + """ + 创建模拟的驾驶数据(图像和转向角) + """ + os.makedirs(data_dir, exist_ok=True) + os.makedirs(os.path.join(data_dir, 'images'), exist_ok=True) + + # 生成转向角(-45度到45度之间) + steering_angles = np.random.uniform(-45, 45, num_samples) + + # 创建CSV文件 + data = {'image_path': [], 'steering_angle': []} + + for i in range(num_samples): + # 生成模拟图像(道路场景) + img = np.zeros((240, 320, 3), dtype=np.uint8) + + # 绘制道路 + cv2.rectangle(img, (100, 0), (220, 240), (100, 100, 100), -1) + + # 绘制车道线 + cv2.line(img, (130, 0), (160, 240), (255, 255, 255), 2) + cv2.line(img, (190, 0), (160, 240), (255, 255, 255), 2) + + # 根据转向角调整车道线 + angle_rad = np.radians(steering_angles[i]) + offset = int(50 * np.tan(angle_rad)) + + cv2.line(img, (130 + offset, 0), (160 + offset, 240), (0, 255, 0), 2) + cv2.line(img, (190 + offset, 0), (160 + offset, 240), (0, 255, 0), 2) + + # 保存图像 + img_path = os.path.join(data_dir, 'images', f'{i:04d}.jpg') + cv2.imwrite(img_path, img) + + data['image_path'].append(img_path) + data['steering_angle'].append(steering_angles[i]) + + # 保存CSV文件 + df = pd.DataFrame(data) + df.to_csv(os.path.join(data_dir, 'driving_log.csv'), index=False) + print(f"生成 {num_samples} 个模拟样本") + return df + + +# 创建模拟数据 +data_dir = 'simulated_data' +df = create_simulated_data(data_dir, num_samples=2000) + + +# 数据增强函数 +def augment_image(img, angle): + """ + 对图像进行增强处理 + """ + # 随机水平翻转 + if np.random.rand() > 0.5: + img = cv2.flip(img, 1) + angle = -angle + + # 随机调整亮度 + hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) + brightness = np.random.uniform(0.7, 1.3) + hsv[:, :, 2] = np.clip(hsv[:, :, 2] * brightness, 0, 255) + img = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB) + + # 随机裁剪 + img = img[50:190, :, :] # 裁剪天空和地面部分 + + # 随机平移 + tx = np.random.randint(-20, 20) + ty = np.random.randint(-10, 10) + M = np.float32([[1, 0, tx], [0, 1, ty]]) + img = cv2.warpAffine(img, M, (img.shape[1], img.shape[0])) + + return img, angle + + +# 数据生成器 +def data_generator(df, batch_size=32, augment=True): + """ + 生成批量训练数据 + """ + while True: + batch_images = [] + batch_angles = [] + + # 随机打乱数据 + shuffled_df = df.sample(frac=1).reset_index(drop=True) + + for i in range(batch_size): + # 获取图像路径和转向角 + img_path = shuffled_df.iloc[i]['image_path'] + angle = shuffled_df.iloc[i]['steering_angle'] + + # 读取图像 + img = cv2.imread(img_path) + img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) + + # 数据增强 + if augment: + img, angle = augment_image(img, angle) + + # 图像预处理 + img = cv2.resize(img, (200, 66)) # 适应NVIDIA模型输入 + img = img / 255.0 # 归一化 + + batch_images.append(img) + batch_angles.append(angle) + + yield np.array(batch_images), np.array(batch_angles) + + +# 划分训练集和验证集 +train_df, val_df = train_test_split(df, test_size=0.2, random_state=42) + +# 创建数据生成器 +train_generator = data_generator(train_df, batch_size=32, augment=True) +val_generator = data_generator(val_df, batch_size=32, augment=False) + + +# -------------------------- +# 2. 构建深度学习模型 +# -------------------------- +def build_model(): + """ + 构建基于CNN的转向角预测模型(参考NVIDIA架构) + """ + model = Sequential() + + # 图像预处理层 + model.add(Lambda(lambda x: x / 255.0 - 0.5, input_shape=(66, 200, 3))) + + # 卷积层 + model.add(Conv2D(24, (5, 5), strides=(2, 2), activation='relu')) + model.add(Conv2D(36, (5, 5), strides=(2, 2), activation='relu')) + model.add(Conv2D(48, (5, 5), strides=(2, 2), activation='relu')) + model.add(Conv2D(64, (3, 3), activation='relu')) + model.add(Conv2D(64, (3, 3), activation='relu')) + + # 全连接层 + model.add(Flatten()) + model.add(Dense(100, activation='relu')) + model.add(Dropout(0.5)) + model.add(Dense(50, activation='relu')) + model.add(Dropout(0.5)) + model.add(Dense(10, activation='relu')) + model.add(Dense(1)) # 输出转向角 + + # 编译模型 + model.compile(optimizer=Adam(learning_rate=0.001), loss='mse') + + return model + + +# 构建模型 +model = build_model() +model.summary() + +# -------------------------- +# 3. 训练模型 +# -------------------------- +# 定义回调函数 +checkpoint = ModelCheckpoint( + 'best_model.h5', + monitor='val_loss', + save_best_only=True, + mode='min', + verbose=1 +) + +early_stop = EarlyStopping( + monitor='val_loss', + patience=5, + mode='min', + verbose=1, + restore_best_weights=True +) + +# 训练模型 +history = model.fit( + train_generator, + steps_per_epoch=len(train_df) // 32, + epochs=30, + validation_data=val_generator, + validation_steps=len(val_df) // 32, + callbacks=[checkpoint, early_stop], + verbose=1 +) + +# 绘制训练曲线 +plt.figure(figsize=(10, 5)) +plt.plot(history.history['loss'], label='训练损失') +plt.plot(history.history['val_loss'], label='验证损失') +plt.xlabel('Epoch') +plt.ylabel('MSE损失') +plt.legend() +plt.title('训练过程') +plt.show() + +# -------------------------- +# 4. 模型评估与实时预测 +# -------------------------- +# 加载最佳模型 +best_model = load_model('best_model.h5') + +# 在验证集上评估 +val_loss = best_model.evaluate(val_generator, steps=len(val_df) // 32, verbose=1) +print(f"验证集损失: {val_loss:.4f}") + + +# 实时预测演示 +def real_time_prediction(model): + """ + 使用摄像头进行实时转向角预测 + """ + cap = cv2.VideoCapture(0) + cap.set(3, 320) # 设置宽度 + cap.set(4, 240) # 设置高度 + + while True: + ret, frame = cap.read() + if not ret: + break + + # 图像预处理 + img = frame[50:190, :, :] # 裁剪 + img = cv2.resize(img, (200, 66)) # 调整尺寸 + img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 转换颜色空间 + img = img / 255.0 # 归一化 + img = np.expand_dims(img, axis=0) # 增加批次维度 + + # 预测转向角 + steering_angle = model.predict(img)[0][0] + + # 在图像上显示转向角 + cv2.putText( + frame, + f"Steering Angle: {steering_angle:.2f} deg", + (10, 30), + cv2.FONT_HERSHEY_SIMPLEX, + 1, + (0, 255, 0), + 2 + ) + + # 显示图像 + cv2.imshow('Autonomous Driving', frame) + + # 按'q'退出 + if cv2.waitKey(1) & 0xFF == ord('q'): + break + + cap.release() + cv2.destroyAllWindows() + + +# 运行实时预测 +print("开始实时预测... 按'q'退出") +real_time_prediction(best_model) \ No newline at end of file From dd24e637cd68fed9ec2ad74788ea439edda13e05 Mon Sep 17 00:00:00 2001 From: ybnfsh <2329959058@qq.com> Date: Mon, 24 Nov 2025 09:25:56 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E6=97=A0=E4=BA=BA=E8=BD=A6=E6=96=B9?= =?UTF-8?q?=E5=90=91=E6=94=B9=E5=8F=98=E7=9A=84=E6=B7=B1=E5=BA=A6=E5=AD=A6?= =?UTF-8?q?=E4=B9=A0=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driverless _car_yb/{main.direction.py => main.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/driverless _car_yb/{main.direction.py => main.py} (100%) diff --git a/src/driverless _car_yb/main.direction.py b/src/driverless _car_yb/main.py similarity index 100% rename from src/driverless _car_yb/main.direction.py rename to src/driverless _car_yb/main.py From c0478ec56e1bb82e921b729753e4257b317b28ed Mon Sep 17 00:00:00 2001 From: ybnfsh <2329959058@qq.com> Date: Mon, 24 Nov 2025 09:32:35 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E6=97=A0=E4=BA=BA=E8=BD=A6=E6=96=B9?= =?UTF-8?q?=E5=90=91=E6=94=B9=E5=8F=98=E7=9A=84=E6=B7=B1=E5=BA=A6=E5=AD=A6?= =?UTF-8?q?=E4=B9=A0=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driverless _car_yb/README.md | 161 +++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 src/driverless _car_yb/README.md diff --git a/src/driverless _car_yb/README.md b/src/driverless _car_yb/README.md new file mode 100644 index 0000000000..df84ba0f70 --- /dev/null +++ b/src/driverless _car_yb/README.md @@ -0,0 +1,161 @@ +无人车import torch +import torch.nn as nn +import torch.optim as optim +import numpy as np +import pandas as pd +from sklearn.model_selection import train_test_split +from sklearn.preprocessing import StandardScaler +import matplotlib.pyplot as plt + +# 设置随机种子,保证结果可复现 +torch.manual_seed(42) +np.random.seed(42) + + +class SpeedPredictor(nn.Module): + """无人车速度预测模型:使用LSTM处理时序数据""" + def __init__(self, input_size, hidden_size, num_layers, output_size=1): + super(SpeedPredictor, self).__init__() + self.lstm = nn.LSTM( + input_size=input_size, # 输入特征数(如速度、加速度、方向盘角度等) + hidden_size=hidden_size, # LSTM隐藏层大小 + num_layers=num_layers, # LSTM层数 + batch_first=True # 输入格式为(batch, seq_len, input_size) + ) + self.fc = nn.Linear(hidden_size, output_size) # 输出层(预测未来速度) + + def forward(self, x): + # x shape: (batch_size, seq_len, input_size) + lstm_out, _ = self.lstm(x) # lstm_out shape: (batch_size, seq_len, hidden_size) + # 取最后一个时间步的输出用于预测 + last_out = lstm_out[:, -1, :] # shape: (batch_size, hidden_size) + pred = self.fc(last_out) # shape: (batch_size, output_size) + return pred + + +def create_sequences(data, seq_len, pred_len=1): + """ + 将时序数据转换为输入序列和标签 + data: 原始数据(特征矩阵) + seq_len: 输入序列长度(用过去多少个时间步预测未来) + pred_len: 预测未来多少个时间步(这里简化为1) + """ + xs, ys = [], [] + for i in range(len(data) - seq_len - pred_len + 1): + x = data[i:(i + seq_len)] # 输入序列(过去seq_len个时间步的特征) + y = data[i + seq_len:i + seq_len + pred_len, 0] # 标签(未来1个时间步的速度,假设第0列是速度) + xs.append(x) + ys.append(y) + return np.array(xs), np.array(ys) + + +def main(): + # 1. 数据准备(这里使用模拟数据,实际应用中替换为真实传感器数据) + # 模拟特征:[速度(m/s), 加速度(m/s²), 方向盘角度(°), 油门开度(%), 刹车压力(bar)] + num_samples = 10000 + time = np.linspace(0, 100, num_samples) + speed = 10 + 5 * np.sin(time) + np.random.normal(0, 0.5, num_samples) # 带噪声的正弦曲线模拟速度 + acceleration = np.gradient(speed, time) # 加速度(速度的导数) + steering = 10 * np.sin(time/2) + np.random.normal(0, 1, num_samples) # 方向盘角度 + throttle = 30 + 10 * np.sin(time/3) + np.random.normal(0, 2, num_samples) # 油门开度 + brake = np.where(speed < 8, 5 + np.random.normal(0, 1, num_samples), np.random.normal(0, 0.5, num_samples)) # 刹车压力 + + # 组合成特征矩阵 + data = np.column_stack([speed, acceleration, steering, throttle, brake]) + + # 2. 数据预处理 + scaler = StandardScaler() # 标准化(均值为0,方差为1) + data_scaled = scaler.fit_transform(data) + + # 创建序列数据(用过去10个时间步预测未来1个时间步的速度) + seq_len = 10 + X, y = create_sequences(data_scaled, seq_len) + + # 划分训练集和测试集 + X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False) # 时序数据不打乱顺序 + + # 转换为PyTorch张量 + X_train = torch.FloatTensor(X_train) + y_train = torch.FloatTensor(y_train) + X_test = torch.FloatTensor(X_test) + y_test = torch.FloatTensor(y_test) + + # 3. 模型初始化 + input_size = X_train.shape[2] # 特征数(这里是5) + hidden_size = 64 + num_layers = 2 + model = SpeedPredictor(input_size, hidden_size, num_layers) + + # 4. 定义损失函数和优化器 + criterion = nn.MSELoss() # 均方误差损失(回归任务) + optimizer = optim.Adam(model.parameters(), lr=0.001) + + # 5. 模型训练 + epochs = 50 + batch_size = 32 + train_losses = [] + test_losses = [] + + for epoch in range(epochs): + model.train() # 训练模式 + epoch_loss = 0 + # 分批训练 + for i in range(0, len(X_train), batch_size): + batch_X = X_train[i:i+batch_size] + batch_y = y_train[i:i+batch_size] + + optimizer.zero_grad() # 清零梯度 + outputs = model(batch_X) + loss = criterion(outputs, batch_y) + loss.backward() # 反向传播 + optimizer.step() # 更新参数 + + epoch_loss += loss.item() * batch_X.size(0) # 累计损失 + + train_loss = epoch_loss / len(X_train) + train_losses.append(train_loss) + + # 测试集验证 + model.eval() # 评估模式 + with torch.no_grad(): + y_pred = model(X_test) + test_loss = criterion(y_pred, y_test).item() + test_losses.append(test_loss) + + if (epoch + 1) % 5 == 0: + print(f'Epoch [{epoch+1}/{epochs}], Train Loss: {train_loss:.6f}, Test Loss: {test_loss:.6f}') + + # 6. 结果可视化 + # 反标准化(将预测结果转换为原始速度尺度) + # 构造反标准化需要的虚拟特征矩阵(仅用于恢复速度的尺度) + dummy = np.zeros_like(data_scaled[:len(y_test)]) + dummy[:, 0] = y_test.numpy().flatten() # 测试集真实速度(标准化后) + y_test_original = scaler.inverse_transform(dummy)[:, 0] # 原始尺度真实速度 + + dummy_pred = np.zeros_like(data_scaled[:len(y_test)]) + dummy_pred[:, 0] = y_pred.numpy().flatten() # 预测速度(标准化后) + y_pred_original = scaler.inverse_transform(dummy_pred)[:, 0] # 原始尺度预测速度 + + # 绘制预测 vs 真实值 + plt.figure(figsize=(12, 6)) + plt.plot(y_test_original, label='真实速度', alpha=0.7) + plt.plot(y_pred_original, label='预测速度', alpha=0.7) + plt.xlabel('时间步') + plt.ylabel('速度 (m/s)') + plt.title('无人车速度预测结果') + plt.legend() + plt.show() + + # 绘制损失曲线 + plt.figure(figsize=(12, 6)) + plt.plot(train_losses, label='训练损失') + plt.plot(test_losses, label='测试损失') + plt.xlabel('Epoch') + plt.ylabel('MSE损失') + plt.title('训练与测试损失曲线') + plt.legend() + plt.show() + + +if __name__ == '__main__': + main()这段代码有什么功能 \ No newline at end of file From 73f98bda8377bd445321a641f6a72ec3b0342e43 Mon Sep 17 00:00:00 2001 From: ybnfsh <2329959058@qq.com> Date: Mon, 24 Nov 2025 10:54:11 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.gitignore | 3 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 7 + .idea/modules.xml | 8 + .idea/nn.iml | 14 + .idea/vcs.xml | 6 + src/driverless _car_yb/README.md | 161 ---------- src/driverless _car_yb/main.py | 275 ------------------ 8 files changed, 44 insertions(+), 436 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/nn.iml create mode 100644 .idea/vcs.xml delete mode 100644 src/driverless _car_yb/README.md delete mode 100644 src/driverless _car_yb/main.py diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000..359bb5307e --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000000..105ce2da2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000000..25d4c9c531 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000..0e01bed9d6 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/nn.iml b/.idea/nn.iml new file mode 100644 index 0000000000..a80c2ef563 --- /dev/null +++ b/.idea/nn.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000..35eb1ddfbb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/driverless _car_yb/README.md b/src/driverless _car_yb/README.md deleted file mode 100644 index df84ba0f70..0000000000 --- a/src/driverless _car_yb/README.md +++ /dev/null @@ -1,161 +0,0 @@ -无人车import torch -import torch.nn as nn -import torch.optim as optim -import numpy as np -import pandas as pd -from sklearn.model_selection import train_test_split -from sklearn.preprocessing import StandardScaler -import matplotlib.pyplot as plt - -# 设置随机种子,保证结果可复现 -torch.manual_seed(42) -np.random.seed(42) - - -class SpeedPredictor(nn.Module): - """无人车速度预测模型:使用LSTM处理时序数据""" - def __init__(self, input_size, hidden_size, num_layers, output_size=1): - super(SpeedPredictor, self).__init__() - self.lstm = nn.LSTM( - input_size=input_size, # 输入特征数(如速度、加速度、方向盘角度等) - hidden_size=hidden_size, # LSTM隐藏层大小 - num_layers=num_layers, # LSTM层数 - batch_first=True # 输入格式为(batch, seq_len, input_size) - ) - self.fc = nn.Linear(hidden_size, output_size) # 输出层(预测未来速度) - - def forward(self, x): - # x shape: (batch_size, seq_len, input_size) - lstm_out, _ = self.lstm(x) # lstm_out shape: (batch_size, seq_len, hidden_size) - # 取最后一个时间步的输出用于预测 - last_out = lstm_out[:, -1, :] # shape: (batch_size, hidden_size) - pred = self.fc(last_out) # shape: (batch_size, output_size) - return pred - - -def create_sequences(data, seq_len, pred_len=1): - """ - 将时序数据转换为输入序列和标签 - data: 原始数据(特征矩阵) - seq_len: 输入序列长度(用过去多少个时间步预测未来) - pred_len: 预测未来多少个时间步(这里简化为1) - """ - xs, ys = [], [] - for i in range(len(data) - seq_len - pred_len + 1): - x = data[i:(i + seq_len)] # 输入序列(过去seq_len个时间步的特征) - y = data[i + seq_len:i + seq_len + pred_len, 0] # 标签(未来1个时间步的速度,假设第0列是速度) - xs.append(x) - ys.append(y) - return np.array(xs), np.array(ys) - - -def main(): - # 1. 数据准备(这里使用模拟数据,实际应用中替换为真实传感器数据) - # 模拟特征:[速度(m/s), 加速度(m/s²), 方向盘角度(°), 油门开度(%), 刹车压力(bar)] - num_samples = 10000 - time = np.linspace(0, 100, num_samples) - speed = 10 + 5 * np.sin(time) + np.random.normal(0, 0.5, num_samples) # 带噪声的正弦曲线模拟速度 - acceleration = np.gradient(speed, time) # 加速度(速度的导数) - steering = 10 * np.sin(time/2) + np.random.normal(0, 1, num_samples) # 方向盘角度 - throttle = 30 + 10 * np.sin(time/3) + np.random.normal(0, 2, num_samples) # 油门开度 - brake = np.where(speed < 8, 5 + np.random.normal(0, 1, num_samples), np.random.normal(0, 0.5, num_samples)) # 刹车压力 - - # 组合成特征矩阵 - data = np.column_stack([speed, acceleration, steering, throttle, brake]) - - # 2. 数据预处理 - scaler = StandardScaler() # 标准化(均值为0,方差为1) - data_scaled = scaler.fit_transform(data) - - # 创建序列数据(用过去10个时间步预测未来1个时间步的速度) - seq_len = 10 - X, y = create_sequences(data_scaled, seq_len) - - # 划分训练集和测试集 - X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False) # 时序数据不打乱顺序 - - # 转换为PyTorch张量 - X_train = torch.FloatTensor(X_train) - y_train = torch.FloatTensor(y_train) - X_test = torch.FloatTensor(X_test) - y_test = torch.FloatTensor(y_test) - - # 3. 模型初始化 - input_size = X_train.shape[2] # 特征数(这里是5) - hidden_size = 64 - num_layers = 2 - model = SpeedPredictor(input_size, hidden_size, num_layers) - - # 4. 定义损失函数和优化器 - criterion = nn.MSELoss() # 均方误差损失(回归任务) - optimizer = optim.Adam(model.parameters(), lr=0.001) - - # 5. 模型训练 - epochs = 50 - batch_size = 32 - train_losses = [] - test_losses = [] - - for epoch in range(epochs): - model.train() # 训练模式 - epoch_loss = 0 - # 分批训练 - for i in range(0, len(X_train), batch_size): - batch_X = X_train[i:i+batch_size] - batch_y = y_train[i:i+batch_size] - - optimizer.zero_grad() # 清零梯度 - outputs = model(batch_X) - loss = criterion(outputs, batch_y) - loss.backward() # 反向传播 - optimizer.step() # 更新参数 - - epoch_loss += loss.item() * batch_X.size(0) # 累计损失 - - train_loss = epoch_loss / len(X_train) - train_losses.append(train_loss) - - # 测试集验证 - model.eval() # 评估模式 - with torch.no_grad(): - y_pred = model(X_test) - test_loss = criterion(y_pred, y_test).item() - test_losses.append(test_loss) - - if (epoch + 1) % 5 == 0: - print(f'Epoch [{epoch+1}/{epochs}], Train Loss: {train_loss:.6f}, Test Loss: {test_loss:.6f}') - - # 6. 结果可视化 - # 反标准化(将预测结果转换为原始速度尺度) - # 构造反标准化需要的虚拟特征矩阵(仅用于恢复速度的尺度) - dummy = np.zeros_like(data_scaled[:len(y_test)]) - dummy[:, 0] = y_test.numpy().flatten() # 测试集真实速度(标准化后) - y_test_original = scaler.inverse_transform(dummy)[:, 0] # 原始尺度真实速度 - - dummy_pred = np.zeros_like(data_scaled[:len(y_test)]) - dummy_pred[:, 0] = y_pred.numpy().flatten() # 预测速度(标准化后) - y_pred_original = scaler.inverse_transform(dummy_pred)[:, 0] # 原始尺度预测速度 - - # 绘制预测 vs 真实值 - plt.figure(figsize=(12, 6)) - plt.plot(y_test_original, label='真实速度', alpha=0.7) - plt.plot(y_pred_original, label='预测速度', alpha=0.7) - plt.xlabel('时间步') - plt.ylabel('速度 (m/s)') - plt.title('无人车速度预测结果') - plt.legend() - plt.show() - - # 绘制损失曲线 - plt.figure(figsize=(12, 6)) - plt.plot(train_losses, label='训练损失') - plt.plot(test_losses, label='测试损失') - plt.xlabel('Epoch') - plt.ylabel('MSE损失') - plt.title('训练与测试损失曲线') - plt.legend() - plt.show() - - -if __name__ == '__main__': - main()这段代码有什么功能 \ No newline at end of file diff --git a/src/driverless _car_yb/main.py b/src/driverless _car_yb/main.py deleted file mode 100644 index efc22d79eb..0000000000 --- a/src/driverless _car_yb/main.py +++ /dev/null @@ -1,275 +0,0 @@ -import os -import cv2 -import numpy as np -import pandas as pd -import matplotlib.pyplot as plt -from sklearn.model_selection import train_test_split -from tensorflow.keras.models import Sequential, load_model -from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, Lambda -from tensorflow.keras.optimizers import Adam -from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping - - -# -------------------------- -# 1. 数据生成与预处理 -# -------------------------- -def create_simulated_data(data_dir, num_samples=1000): - """ - 创建模拟的驾驶数据(图像和转向角) - """ - os.makedirs(data_dir, exist_ok=True) - os.makedirs(os.path.join(data_dir, 'images'), exist_ok=True) - - # 生成转向角(-45度到45度之间) - steering_angles = np.random.uniform(-45, 45, num_samples) - - # 创建CSV文件 - data = {'image_path': [], 'steering_angle': []} - - for i in range(num_samples): - # 生成模拟图像(道路场景) - img = np.zeros((240, 320, 3), dtype=np.uint8) - - # 绘制道路 - cv2.rectangle(img, (100, 0), (220, 240), (100, 100, 100), -1) - - # 绘制车道线 - cv2.line(img, (130, 0), (160, 240), (255, 255, 255), 2) - cv2.line(img, (190, 0), (160, 240), (255, 255, 255), 2) - - # 根据转向角调整车道线 - angle_rad = np.radians(steering_angles[i]) - offset = int(50 * np.tan(angle_rad)) - - cv2.line(img, (130 + offset, 0), (160 + offset, 240), (0, 255, 0), 2) - cv2.line(img, (190 + offset, 0), (160 + offset, 240), (0, 255, 0), 2) - - # 保存图像 - img_path = os.path.join(data_dir, 'images', f'{i:04d}.jpg') - cv2.imwrite(img_path, img) - - data['image_path'].append(img_path) - data['steering_angle'].append(steering_angles[i]) - - # 保存CSV文件 - df = pd.DataFrame(data) - df.to_csv(os.path.join(data_dir, 'driving_log.csv'), index=False) - print(f"生成 {num_samples} 个模拟样本") - return df - - -# 创建模拟数据 -data_dir = 'simulated_data' -df = create_simulated_data(data_dir, num_samples=2000) - - -# 数据增强函数 -def augment_image(img, angle): - """ - 对图像进行增强处理 - """ - # 随机水平翻转 - if np.random.rand() > 0.5: - img = cv2.flip(img, 1) - angle = -angle - - # 随机调整亮度 - hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) - brightness = np.random.uniform(0.7, 1.3) - hsv[:, :, 2] = np.clip(hsv[:, :, 2] * brightness, 0, 255) - img = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB) - - # 随机裁剪 - img = img[50:190, :, :] # 裁剪天空和地面部分 - - # 随机平移 - tx = np.random.randint(-20, 20) - ty = np.random.randint(-10, 10) - M = np.float32([[1, 0, tx], [0, 1, ty]]) - img = cv2.warpAffine(img, M, (img.shape[1], img.shape[0])) - - return img, angle - - -# 数据生成器 -def data_generator(df, batch_size=32, augment=True): - """ - 生成批量训练数据 - """ - while True: - batch_images = [] - batch_angles = [] - - # 随机打乱数据 - shuffled_df = df.sample(frac=1).reset_index(drop=True) - - for i in range(batch_size): - # 获取图像路径和转向角 - img_path = shuffled_df.iloc[i]['image_path'] - angle = shuffled_df.iloc[i]['steering_angle'] - - # 读取图像 - img = cv2.imread(img_path) - img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) - - # 数据增强 - if augment: - img, angle = augment_image(img, angle) - - # 图像预处理 - img = cv2.resize(img, (200, 66)) # 适应NVIDIA模型输入 - img = img / 255.0 # 归一化 - - batch_images.append(img) - batch_angles.append(angle) - - yield np.array(batch_images), np.array(batch_angles) - - -# 划分训练集和验证集 -train_df, val_df = train_test_split(df, test_size=0.2, random_state=42) - -# 创建数据生成器 -train_generator = data_generator(train_df, batch_size=32, augment=True) -val_generator = data_generator(val_df, batch_size=32, augment=False) - - -# -------------------------- -# 2. 构建深度学习模型 -# -------------------------- -def build_model(): - """ - 构建基于CNN的转向角预测模型(参考NVIDIA架构) - """ - model = Sequential() - - # 图像预处理层 - model.add(Lambda(lambda x: x / 255.0 - 0.5, input_shape=(66, 200, 3))) - - # 卷积层 - model.add(Conv2D(24, (5, 5), strides=(2, 2), activation='relu')) - model.add(Conv2D(36, (5, 5), strides=(2, 2), activation='relu')) - model.add(Conv2D(48, (5, 5), strides=(2, 2), activation='relu')) - model.add(Conv2D(64, (3, 3), activation='relu')) - model.add(Conv2D(64, (3, 3), activation='relu')) - - # 全连接层 - model.add(Flatten()) - model.add(Dense(100, activation='relu')) - model.add(Dropout(0.5)) - model.add(Dense(50, activation='relu')) - model.add(Dropout(0.5)) - model.add(Dense(10, activation='relu')) - model.add(Dense(1)) # 输出转向角 - - # 编译模型 - model.compile(optimizer=Adam(learning_rate=0.001), loss='mse') - - return model - - -# 构建模型 -model = build_model() -model.summary() - -# -------------------------- -# 3. 训练模型 -# -------------------------- -# 定义回调函数 -checkpoint = ModelCheckpoint( - 'best_model.h5', - monitor='val_loss', - save_best_only=True, - mode='min', - verbose=1 -) - -early_stop = EarlyStopping( - monitor='val_loss', - patience=5, - mode='min', - verbose=1, - restore_best_weights=True -) - -# 训练模型 -history = model.fit( - train_generator, - steps_per_epoch=len(train_df) // 32, - epochs=30, - validation_data=val_generator, - validation_steps=len(val_df) // 32, - callbacks=[checkpoint, early_stop], - verbose=1 -) - -# 绘制训练曲线 -plt.figure(figsize=(10, 5)) -plt.plot(history.history['loss'], label='训练损失') -plt.plot(history.history['val_loss'], label='验证损失') -plt.xlabel('Epoch') -plt.ylabel('MSE损失') -plt.legend() -plt.title('训练过程') -plt.show() - -# -------------------------- -# 4. 模型评估与实时预测 -# -------------------------- -# 加载最佳模型 -best_model = load_model('best_model.h5') - -# 在验证集上评估 -val_loss = best_model.evaluate(val_generator, steps=len(val_df) // 32, verbose=1) -print(f"验证集损失: {val_loss:.4f}") - - -# 实时预测演示 -def real_time_prediction(model): - """ - 使用摄像头进行实时转向角预测 - """ - cap = cv2.VideoCapture(0) - cap.set(3, 320) # 设置宽度 - cap.set(4, 240) # 设置高度 - - while True: - ret, frame = cap.read() - if not ret: - break - - # 图像预处理 - img = frame[50:190, :, :] # 裁剪 - img = cv2.resize(img, (200, 66)) # 调整尺寸 - img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 转换颜色空间 - img = img / 255.0 # 归一化 - img = np.expand_dims(img, axis=0) # 增加批次维度 - - # 预测转向角 - steering_angle = model.predict(img)[0][0] - - # 在图像上显示转向角 - cv2.putText( - frame, - f"Steering Angle: {steering_angle:.2f} deg", - (10, 30), - cv2.FONT_HERSHEY_SIMPLEX, - 1, - (0, 255, 0), - 2 - ) - - # 显示图像 - cv2.imshow('Autonomous Driving', frame) - - # 按'q'退出 - if cv2.waitKey(1) & 0xFF == ord('q'): - break - - cap.release() - cv2.destroyAllWindows() - - -# 运行实时预测 -print("开始实时预测... 按'q'退出") -real_time_prediction(best_model) \ No newline at end of file From 91f07a59b24fdeac035b4ec6c4d726399f71ba30 Mon Sep 17 00:00:00 2001 From: ybnfsh <2329959058@qq.com> Date: Tue, 25 Nov 2025 10:44:50 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E6=97=A0=E4=BA=BA?= =?UTF-8?q?=E8=BD=A6=E6=96=B9=E5=90=91=E6=94=B9=E5=8F=98=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driverless_car_yb/main.py | 275 ++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 src/driverless_car_yb/main.py diff --git a/src/driverless_car_yb/main.py b/src/driverless_car_yb/main.py new file mode 100644 index 0000000000..efc22d79eb --- /dev/null +++ b/src/driverless_car_yb/main.py @@ -0,0 +1,275 @@ +import os +import cv2 +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt +from sklearn.model_selection import train_test_split +from tensorflow.keras.models import Sequential, load_model +from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, Lambda +from tensorflow.keras.optimizers import Adam +from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping + + +# -------------------------- +# 1. 数据生成与预处理 +# -------------------------- +def create_simulated_data(data_dir, num_samples=1000): + """ + 创建模拟的驾驶数据(图像和转向角) + """ + os.makedirs(data_dir, exist_ok=True) + os.makedirs(os.path.join(data_dir, 'images'), exist_ok=True) + + # 生成转向角(-45度到45度之间) + steering_angles = np.random.uniform(-45, 45, num_samples) + + # 创建CSV文件 + data = {'image_path': [], 'steering_angle': []} + + for i in range(num_samples): + # 生成模拟图像(道路场景) + img = np.zeros((240, 320, 3), dtype=np.uint8) + + # 绘制道路 + cv2.rectangle(img, (100, 0), (220, 240), (100, 100, 100), -1) + + # 绘制车道线 + cv2.line(img, (130, 0), (160, 240), (255, 255, 255), 2) + cv2.line(img, (190, 0), (160, 240), (255, 255, 255), 2) + + # 根据转向角调整车道线 + angle_rad = np.radians(steering_angles[i]) + offset = int(50 * np.tan(angle_rad)) + + cv2.line(img, (130 + offset, 0), (160 + offset, 240), (0, 255, 0), 2) + cv2.line(img, (190 + offset, 0), (160 + offset, 240), (0, 255, 0), 2) + + # 保存图像 + img_path = os.path.join(data_dir, 'images', f'{i:04d}.jpg') + cv2.imwrite(img_path, img) + + data['image_path'].append(img_path) + data['steering_angle'].append(steering_angles[i]) + + # 保存CSV文件 + df = pd.DataFrame(data) + df.to_csv(os.path.join(data_dir, 'driving_log.csv'), index=False) + print(f"生成 {num_samples} 个模拟样本") + return df + + +# 创建模拟数据 +data_dir = 'simulated_data' +df = create_simulated_data(data_dir, num_samples=2000) + + +# 数据增强函数 +def augment_image(img, angle): + """ + 对图像进行增强处理 + """ + # 随机水平翻转 + if np.random.rand() > 0.5: + img = cv2.flip(img, 1) + angle = -angle + + # 随机调整亮度 + hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) + brightness = np.random.uniform(0.7, 1.3) + hsv[:, :, 2] = np.clip(hsv[:, :, 2] * brightness, 0, 255) + img = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB) + + # 随机裁剪 + img = img[50:190, :, :] # 裁剪天空和地面部分 + + # 随机平移 + tx = np.random.randint(-20, 20) + ty = np.random.randint(-10, 10) + M = np.float32([[1, 0, tx], [0, 1, ty]]) + img = cv2.warpAffine(img, M, (img.shape[1], img.shape[0])) + + return img, angle + + +# 数据生成器 +def data_generator(df, batch_size=32, augment=True): + """ + 生成批量训练数据 + """ + while True: + batch_images = [] + batch_angles = [] + + # 随机打乱数据 + shuffled_df = df.sample(frac=1).reset_index(drop=True) + + for i in range(batch_size): + # 获取图像路径和转向角 + img_path = shuffled_df.iloc[i]['image_path'] + angle = shuffled_df.iloc[i]['steering_angle'] + + # 读取图像 + img = cv2.imread(img_path) + img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) + + # 数据增强 + if augment: + img, angle = augment_image(img, angle) + + # 图像预处理 + img = cv2.resize(img, (200, 66)) # 适应NVIDIA模型输入 + img = img / 255.0 # 归一化 + + batch_images.append(img) + batch_angles.append(angle) + + yield np.array(batch_images), np.array(batch_angles) + + +# 划分训练集和验证集 +train_df, val_df = train_test_split(df, test_size=0.2, random_state=42) + +# 创建数据生成器 +train_generator = data_generator(train_df, batch_size=32, augment=True) +val_generator = data_generator(val_df, batch_size=32, augment=False) + + +# -------------------------- +# 2. 构建深度学习模型 +# -------------------------- +def build_model(): + """ + 构建基于CNN的转向角预测模型(参考NVIDIA架构) + """ + model = Sequential() + + # 图像预处理层 + model.add(Lambda(lambda x: x / 255.0 - 0.5, input_shape=(66, 200, 3))) + + # 卷积层 + model.add(Conv2D(24, (5, 5), strides=(2, 2), activation='relu')) + model.add(Conv2D(36, (5, 5), strides=(2, 2), activation='relu')) + model.add(Conv2D(48, (5, 5), strides=(2, 2), activation='relu')) + model.add(Conv2D(64, (3, 3), activation='relu')) + model.add(Conv2D(64, (3, 3), activation='relu')) + + # 全连接层 + model.add(Flatten()) + model.add(Dense(100, activation='relu')) + model.add(Dropout(0.5)) + model.add(Dense(50, activation='relu')) + model.add(Dropout(0.5)) + model.add(Dense(10, activation='relu')) + model.add(Dense(1)) # 输出转向角 + + # 编译模型 + model.compile(optimizer=Adam(learning_rate=0.001), loss='mse') + + return model + + +# 构建模型 +model = build_model() +model.summary() + +# -------------------------- +# 3. 训练模型 +# -------------------------- +# 定义回调函数 +checkpoint = ModelCheckpoint( + 'best_model.h5', + monitor='val_loss', + save_best_only=True, + mode='min', + verbose=1 +) + +early_stop = EarlyStopping( + monitor='val_loss', + patience=5, + mode='min', + verbose=1, + restore_best_weights=True +) + +# 训练模型 +history = model.fit( + train_generator, + steps_per_epoch=len(train_df) // 32, + epochs=30, + validation_data=val_generator, + validation_steps=len(val_df) // 32, + callbacks=[checkpoint, early_stop], + verbose=1 +) + +# 绘制训练曲线 +plt.figure(figsize=(10, 5)) +plt.plot(history.history['loss'], label='训练损失') +plt.plot(history.history['val_loss'], label='验证损失') +plt.xlabel('Epoch') +plt.ylabel('MSE损失') +plt.legend() +plt.title('训练过程') +plt.show() + +# -------------------------- +# 4. 模型评估与实时预测 +# -------------------------- +# 加载最佳模型 +best_model = load_model('best_model.h5') + +# 在验证集上评估 +val_loss = best_model.evaluate(val_generator, steps=len(val_df) // 32, verbose=1) +print(f"验证集损失: {val_loss:.4f}") + + +# 实时预测演示 +def real_time_prediction(model): + """ + 使用摄像头进行实时转向角预测 + """ + cap = cv2.VideoCapture(0) + cap.set(3, 320) # 设置宽度 + cap.set(4, 240) # 设置高度 + + while True: + ret, frame = cap.read() + if not ret: + break + + # 图像预处理 + img = frame[50:190, :, :] # 裁剪 + img = cv2.resize(img, (200, 66)) # 调整尺寸 + img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 转换颜色空间 + img = img / 255.0 # 归一化 + img = np.expand_dims(img, axis=0) # 增加批次维度 + + # 预测转向角 + steering_angle = model.predict(img)[0][0] + + # 在图像上显示转向角 + cv2.putText( + frame, + f"Steering Angle: {steering_angle:.2f} deg", + (10, 30), + cv2.FONT_HERSHEY_SIMPLEX, + 1, + (0, 255, 0), + 2 + ) + + # 显示图像 + cv2.imshow('Autonomous Driving', frame) + + # 按'q'退出 + if cv2.waitKey(1) & 0xFF == ord('q'): + break + + cap.release() + cv2.destroyAllWindows() + + +# 运行实时预测 +print("开始实时预测... 按'q'退出") +real_time_prediction(best_model) \ No newline at end of file From 95a0709fc6da5e33c2cf720486a7993594596913 Mon Sep 17 00:00:00 2001 From: ybnfsh <2329959058@qq.com> Date: Tue, 25 Nov 2025 10:44:50 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/driverless_car_yb/README.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/driverless_car_yb/README.md b/src/driverless_car_yb/README.md index 8c27ba2124..31c342a6a0 100644 --- a/src/driverless_car_yb/README.md +++ b/src/driverless_car_yb/README.md @@ -1 +1,23 @@ -无人车 \ No newline at end of file +# 无人车项目 + +## 项目简介 +无人车(自动驾驶汽车)是一种集成了人工智能、传感器技术、计算机视觉和机器学习等前沿技术的智能交通工具。该项目旨在开发能够在复杂道路环境中自主导航、避障、识别交通标志并安全行驶的无人驾驶系统。 + +## 核心技术 +**计算机视觉**:通过摄像头识别道路标志、车辆、行人等 +**传感器融合**:整合激光雷达、毫米波雷达等传感器数据 +**路径规划**:基于实时环境信息规划最优行驶路径 +**决策系统**:处理复杂交通场景并做出驾驶决策 +**机器学习**:通过深度学习模型提升驾驶安全性 + +## 主要功能 +自动跟车与变道 +智能避障与紧急制动 +自动泊车 +语音控制与导航 +实时路况分析 + +## 技术优势 +本项目采用模块化架构设计,支持多种传感器配置和算法策略,确保系统的可扩展性和稳定性。通过大规模数据训练和仿真测试,持续优化算法性能。 + +--- \ No newline at end of file