这段代码的主要流程涉及车道线检测模型的训练、加载和在视频上应用检测结果。以下是主要流程的简要概述:
导入库和组件:导入所需的库,包括NumPy、scikit-learn和Keras等。
定义模型结构:定义了一个卷积神经网络(CNN)模型的结构。模型采用卷积层、池化层、上采样层和反卷积层等来实现车道线检测。
加载训练数据:加载训练数据和标签数据,并进行数据预处理。将数据转换为NumPy数组,并对标签进行归一化。
构建和编译模型:使用定义的模型结构来构建CNN模型。使用ImageDataGenerator进行数据增强,然后编译模型,指定优化器和损失函数。
训练模型:使用生成器训练模型,其中数据流通过数据增强生成的批次。指定训练的回合数和批大小,对模型进行训练。
保存模型:冻结模型的层并重新编译,然后将模型结构和权重保存到文件中。
加载和使用模型:加载之前保存的模型文件。在视频中逐帧读取图像,将其传递给模型进行检测,并在原始图像上叠加检测结果。
视频处理循环:循环读取视频的每一帧,将其调整为模型所需的输入大小,进行模型推理,计算平均预测结果,并将检测结果叠加在原始图像上。
退出:通过按下"q"键来退出视频处理循环,并释放资源。
这段代码主要是针对车道线检测模型的训练和应用,通过使用CNN模型,可以实现在视频上检测并绘制车道线的功能。
2.代码
#!/usr/bin/env python
# coding: utf-8
# # 实验:车道线检测
#实验过程
# 模型训练
# 首先导入需要的组件包,Numpy、keras、sklearn等,代码如下:
import numpy as np
import pickle
from sklearn.utils import shuffle
from sklearn.model_selection import train_test_split
# Import necessary items from Keras
from keras.models import Sequential
from keras.layers import Activation, Dropout, UpSampling2D
from keras.layers import Conv2DTranspose, Conv2D, MaxPooling2D
from keras.layers.normalization import BatchNormalization
from keras.preprocessing.image import ImageDataGenerator
from keras import regularizers
# 模型结构定义
# 网络输入层为80 x 160 x 3(RGB)形状的道路图像,标签为80 x 160 x 1,只有G通道重新绘制车道,实现代码如下:
def create_model(input_shape, pool_size):
# 创建网络模型
model = Sequential()
# 对输入层进行归一化处理
model.add(BatchNormalization(input_shape=input_shape))
# 卷积层1,名为Conv1
model.add(Conv2D(8, (3, 3), padding='valid', strides=(1,1), activation = 'relu', name = 'Conv1'))
# 卷积层2
model.add(Conv2D(16, (3, 3), padding='valid', strides=(1,1), activation = 'relu', name = 'Conv2'))
# 最大化层
model.add(MaxPooling2D(pool_size=pool_size))
# 卷积层3
model.add(Conv2D(16, (3, 3), padding='valid', strides=(1,1), activation = 'relu', name = 'Conv3'))
model.add(Dropout(0.2))
# 卷积层4
model.add(Conv2D(32, (3, 3), padding='valid', strides=(1,1), activation = 'relu', name = 'Conv4'))
model.add(Dropout(0.2))
# 卷积层5
model.add(Conv2D(32, (3, 3), padding='valid', strides=(1,1), activation = 'relu', name = 'Conv5'))
model.add(Dropout(0.2))
# 最大化层2
model.add(MaxPooling2D(pool_size=pool_size))
# 卷积层6
model.add(Conv2D(64, (3, 3), padding='valid', strides=(1,1), activation = 'relu', name = 'Conv6'))
model.add(Dropout(0.2))
# 卷积层7
model.add(Conv2D(64, (3, 3), padding='valid', strides=(1,1), activation = 'relu', name = 'Conv7'))
model.add(Dropout(0.2))
# 最大化层3
model.add(MaxPooling2D(pool_size=pool_size))
# 上采样层1
model.add(UpSampling2D(size=pool_size))
# 反卷积层 1
model.add(Conv2DTranspose(64, (3, 3), padding='valid', strides=(1,1), activation = 'relu', name = 'Deconv1'))
model.add(Dropout(0.2))
# 反卷积层 2
model.add(Conv2DTranspose(64, (3, 3), padding='valid', strides=(1,1), activation = 'relu', name = 'Deconv2'))
model.add(Dropout(0.2))
# 上采样层 2
model.add(UpSampling2D(size=pool_size))
# 反卷积层 3
model.add(Conv2DTranspose(32, (3, 3), padding='valid', strides=(1,1), activation = 'relu', name = 'Deconv3'))
model.add(Dropout(0.2))
# 反卷积层 4
model.add(Conv2DTranspose(32, (3, 3), padding='valid', strides=(1,1), activation = 'relu', name = 'Deconv4'))
model.add(Dropout(0.2))
# 反卷积层 5
model.add(Conv2DTranspose(16, (3, 3), padding='valid', strides=(1,1), activation = 'relu', name = 'Deconv5'))
model.add(Dropout(0.2))
# 上采样层 3
model.add(UpSampling2D(size=pool_size))
# 反卷积层 6
model.add(Conv2DTranspose(16, (3, 3), padding='valid', strides=(1,1), activation = 'relu', name = 'Deconv6'))
# 输出层
model.add(Conv2DTranspose(1, (3, 3), padding='valid', strides=(1,1), activation = 'relu', name = 'Final'))
return model
#加载数据
# 加载训练数据
train_images = pickle.load(open("full_CNN_train.p", "rb" ))
# 加载标签数据
labels = pickle.load(open("full_CNN_labels.p", "rb" ))
# 对数据进行预处理
train_images = np.array(train_images)
labels = np.array(labels)
# 对标签进行归一化处理
labels = labels / 255
# 混淆数据
train_images, labels = shuffle(train_images, labels)
# 划分训练集和测试集
X_train, X_val, y_train, y_val = train_test_split(train_images, labels, test_size=0.1)
print("loaded train samples:", len(train_images))
#构建并编译模型
# 定义超参
#批大小
batch_size = 128
#训练回合数
epochs = 10
#池化大小
pool_size = (2, 2)
#输入大小
input_shape = X_train.shape[1:]
# 构建模型
model = create_model(input_shape, pool_size)
# 构建数据生成器实现通道增强
datagen = ImageDataGenerator(channel_shift_range=0.2)
datagen.fit(X_train)
# 编译模型
model.compile(optimizer='Adam', loss='mean_squared_error')
# 可视化模型
model.summary()
#训练模型
model.fit_generator(datagen.flow(X_train, y_train, batch_size=batch_size), steps_per_epoch=len(X_train)/batch_size,
epochs=epochs, verbose=1, validation_data=(X_val, y_val))
# #### 5)保存模型
# Freeze layers since training is done
model.trainable = False
model.compile(optimizer='Adam', loss='mean_squared_error')
# Save model architecture and weights
model.save('full_CNN_model_tiny.h5')
#加载并使用模型
#加载Python相关组件
import numpy
import numpy as np
import cv2
from PIL.Image import Image
from keras.models import load_model
from IPython.display import clear_output, Image, display, HTML
#定义工具类
# 道路线类
class Lanes():
def __init__(self):
self.recent_fit = []
self.avg_fit = []
#图像显示方法
def arrayShow(imageArray):
ret, jpg = cv2.imencode('.jpg', imageArray)
return Image(jpg)
#加载检测模型
# 加载模型
model = load_model('full_CNN_model.h5')
# 读取视频文件和输出检测结果
# 读取input目录下的demo.mp4文件,逐帧读取并交给模型进行检测和识别,然后对检测结果计算其均值,并将检测结果绘制输出。
#读取视频文件
vs = cv2.VideoCapture("input/demo1.mp4")
frameIndex = 0
lanes = Lanes()
#循环读取
while True:
#读取视频帧
(grabbed, frame_source) = vs.read()
if not grabbed:
break
#将视频帧resize为模型的输入大小
frame_show = cv2.resize(frame_source, (576, 288))
frame = cv2.resize(frame_show, (160, 80))
rgb_small_frame = frame[None,:,:,:]
# 模型推理检测
prediction = model.predict(rgb_small_frame)[0] * 255
# 储存预测结果到列表中
lanes.recent_fit.append(prediction)
# 只使用最近的数据
if len(lanes.recent_fit) > 5:
lanes.recent_fit = lanes.recent_fit[1:]
# 计算平均预测结果
lanes.avg_fit = np.mean(np.array([i for i in lanes.recent_fit]), axis = 0)
# Generate fake R & B color dimensions, stack with G
blanks = np.zeros_like(lanes.avg_fit).astype(np.uint8)
lane_drawn = np.dstack((blanks, lanes.avg_fit, blanks))
#恢复成原始视频大小
lane_image = cv2.resize(lane_drawn, (576, 288))
#合并原始图像和检测结果
img = cv2.addWeighted(frame_show, 0.3, lane_image, 0.7, 0,dtype = cv2.CV_32F)
# 清空绘图空间
clear_output(wait=True)
# 显示处理结果
display(arrayShow(img))
#按键盘中的q键退出检测
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 释放资源
print("[INFO] cleaning up...")
vs.release()
cv2.destroyAllWindows()
3.视频在我的主页有,只需要放在对应的路径,就可以运行程序
demo-CSDN直播