基于机器视觉目标检测的车辆识别与信号灯模糊控制配时系统【附代码】
📈 算法与建模领域的探索者 | 专注数据分析与智能模型设计✨ 擅长算法、建模、数据分析💡 matlab、python、仿真✅ 具体问题可以私信或查看文章底部二维码✅ 感恩科研路上每一位志同道合的伙伴!
📈 算法与建模领域的探索者 | 专注数据分析与智能模型设计
✨ 擅长算法、建模、数据分析
💡 matlab、python、仿真
✅ 具体问题可以私信或查看文章底部二维码
✅ 感恩科研路上每一位志同道合的伙伴!
(1)车流量检测中的改进 ViBe 算法设计与优化
在车流量检测环节,针对传统 ViBe 算法在实际交通场景中存在的 “鬼影” 现象和背景模型更新适应性差的问题,提出了多维度优化的改进方案。传统 ViBe 算法在背景模型初始化阶段,由于初始帧中可能存在临时停留的车辆、行人或其他移动物体,这些物体容易被误判为背景的一部分,形成 “鬼影”,导致后续车辆检测时出现误检或漏检。为解决这一问题,改进算法引入图像像素均值参考机制,首先对初始化阶段的多帧图像进行像素级统计,计算每个像素位置在多帧图像中的灰度均值或 RGB 均值,将该均值作为判断 “鬼影” 的基准值。随后,逐一对比模型库中每个像素与对应位置的均值,若两者差值超过预设的合理阈值(该阈值通过大量交通场景样本训练确定,兼顾不同光照、天气条件下的适应性),则判定该像素为 “鬼影” 像素点,并立即从背景模型库中剔除,同时用周围正常背景像素的均值对其进行替换,确保背景模型初始化的准确性。
针对传统 ViBe 算法单一更新速率难以适应复杂交通背景的问题,改进算法创新性地引入像素方差复杂度评判体系。首先,对背景模型库中每个像素位置的多帧数据计算方差,方差越大,表明该区域背景变化越频繁(如路口的树荫晃动、路灯闪烁、临时停车区域等),背景复杂度越高;方差越小,则背景越稳定(如远离路口的固定路面区域)。基于方差大小,将背景复杂度划分为高、中、低三类:高复杂度区域(方差大于预设高阈值)主要包括路口转向区域、临时停车带附近等,这类区域背景变化快,需要较高的模型更新速率,以快速捕捉背景的动态变化,避免将新出现的车辆误判为背景;中复杂度区域(方差介于高阈值与低阈值之间)包括路口主车道非转向区域,采用中等更新速率,在保证检测准确性的同时减少计算资源消耗;低复杂度区域(方差小于预设低阈值)主要为远离路口的稳定路面,采用较低更新速率,避免频繁更新导致背景模型波动。通过这种自适应的背景模型更新策略,改进后的 ViBe 算法能够根据不同区域的背景特性动态调整更新频率,既提升了复杂场景下的背景建模精度,又降低了不必要的计算开销。
在车辆信息获取后的流量统计环节,采用多方法融合的统计策略。首先,通过图像标定工具确定路口需要检测的有效路面区域,排除人行道、绿化带、路边建筑物等非车辆通行区域,划定多个矩形检测区域,每个区域对应一条车道的关键通行段。在这些检测区域内,部署虚拟线圈,虚拟线圈的位置选择在车道中部远离停车线的位置,避免车辆排队时的遮挡影响。当车辆通过虚拟线圈时,会引起线圈区域内像素灰度值或纹理特征的变化,算法通过连续帧对比,检测到这种变化并记录为一次车辆通行,实现对动态车辆流量的实时统计。同时,考虑到路口可能存在车辆临时静止(如红灯等待、拥堵排队)的情况,仅依靠虚拟线圈难以统计静止车辆数目,引入 YOLOv3 目标检测算法进行补充。YOLOv3 算法通过预先训练的交通场景车辆模型,能够快速识别图像中的车辆目标,无论车辆处于运动还是静止状态,都能准确框选出车辆位置并计数。为进一步实现分车道统计,算法在 YOLOv3 识别出车辆后,计算每个车辆目标的质心坐标(通过车辆 bounding box 的几何中心确定),再结合预先标定的车道分界线坐标,判断车辆质心所属的车道,从而分别统计出各车道的动态车辆流量(虚拟线圈统计结果)和静止车辆数目(YOLOv3 统计结果),形成完整的车道级车辆数据,为后续信号灯配时策略的制定提供精准的数据支撑。
(2)基于拥堵强度的两级模糊控制器设计与配时优化
在信号灯配时环节,以城市十字路口为研究对象,针对传统单级模糊控制在拥堵场景下配时灵活性不足、输入参数单一导致配时误差大的问题,构建了基于拥堵强度的两级模糊控制器。传统单级模糊控制通常仅以单一参数(如排队长度、车辆延误时间)作为输入,难以全面反映路口各方向的交通拥堵状况,尤其在高峰时段多方向同时拥堵时,容易出现配时方案偏向某一方向而导致其他方向拥堵加剧的情况。此外,以排队长度作为输入参数时,由于排队车辆可能存在遮挡、车型大小差异等问题,实际测量的排队长度与真实值存在偏差,进一步影响配时准确性。
改进后的两级模糊控制器首先优化了输入参数的选取,将 “拥堵强度” 作为核心输入指标。拥堵强度的计算综合了多个交通参数:首先,根据前文车流量检测得到的各车道车辆数目(包括动态流量和静止数目),计算各车道的车辆密度(单位长度车道内的车辆数);其次,通过视频图像分析车辆的平均行驶速度(拥堵时车辆速度显著降低);最后,结合历史交通数据中各时段的拥堵阈值,将车辆密度和平均速度进行归一化处理,得到 0-1 之间的拥堵强度值(0 表示完全畅通,1 表示严重拥堵)。与单一的排队长度相比,拥堵强度能够更全面、准确地反映路口各方向的交通负荷状况。
两级模糊控制器的结构设计分为第一级(方向级)和第二级(相位级)。第一级控制器以十字路口四个方向(东、西、南、北)的拥堵强度为输入,通过模糊推理判断当前各方向的交通紧急程度,初步确定优先通行的方向组合(如东 - 西方向优先或南 - 北方向优先),并输出该优先方向组合的初始绿灯时长范围(如 40-60 秒)。这一级的作用是从宏观上协调各方向的通行优先级,避免某一方向长期拥堵。第二级控制器则在第一级确定的优先方向组合基础上,进一步细化配时方案,以当前通行相位(如东向直行)的拥堵强度和下一通行相位(如东向左转)的拥堵强度作为输入,以当前通行相位的绿灯延长时间作为输出。例如,若当前东向直行相位的拥堵强度较高(如 0.8),且下一东向左转相位的拥堵强度较低(如 0.3),则通过模糊推理判断当前直行方向仍有大量车辆等待通行,需延长绿灯时间(如延长 10 秒);若当前相位拥堵强度较低(如 0.2),而下一相位拥堵强度较高(如 0.7),则缩短当前相位绿灯时间(如不延长或仅延长 2 秒),避免下一相位拥堵加剧。
在模糊推理过程中,采用三角形隶属度函数对输入的拥堵强度和输出的绿灯延长时间进行模糊化处理,将拥堵强度划分为 “低拥堵”“中拥堵”“高拥堵” 三个模糊子集,将绿灯延长时间划分为 “短延长”“中延长”“长延长” 三个模糊子集。根据大量实际交通场景的配时经验,制定模糊规则库,例如 “若当前相位拥堵强度为高拥堵且下一相位拥堵强度为低拥堵,则绿灯延长时间为长延长”“若当前相位拥堵强度为中拥堵且下一相位拥堵强度为中拥堵,则绿灯延长时间为中延长” 等。模糊推理后,采用重心法对模糊输出进行清晰化处理,将模糊量转换为具体的绿灯延长时间数值,最终确定当前相位的实际绿灯时长(初始绿灯时长 + 绿灯延长时间)。通过这种两级模糊控制结构,配时方案能够同时兼顾当前相位的车辆通行需求和下一相位的拥堵预判,显著提升了拥堵场景下配时策略的灵活性和准确性。
(3)实验验证与性能分析
为验证改进算法的有效性,设计了多场景、多指标的对比实验,实验数据来源于真实城市十字路口的视频监控数据(涵盖早高峰、晚高峰、平峰、畅通四个时段,每个时段采集连续 2 小时视频,视频分辨率为 1920×1080,帧率为 25fps),同时搭建了仿真平台(基于 VISSIM 交通仿真软件与 MATLAB 联合仿真),对车流量检测精度和信号灯配时效果进行量化分析。
在车流量检测性能验证中,将改进的 ViBe 算法与传统 ViBe 算法进行对比,选取车辆检测准确率、漏检率、误检率作为评价指标。实验结果显示,在早高峰拥堵场景下,传统 ViBe 算法由于 “鬼影” 和背景更新不及时,车辆检测准确率仅为 76.89%,漏检率达 18.23%,误检率为 4.88%;而改进的 ViBe 算法通过 “鬼影” 消除和自适应背景更新,准确率提升至 94.07%,漏检率降至 5.12%,误检率降至 0.81%。在晚高峰、平峰、畅通场景下,改进算法的准确率均保持在 92% 以上,相比传统算法平均提升 16.18 个百分点。对于 YOLOv3 算法的车辆数目统计验证,选取不同车型(轿车、SUV、公交车、货车)和不同遮挡程度(无遮挡、轻度遮挡、中度遮挡)的样本进行测试,结果显示其车辆数目检测综合准确率达到 94.97%,其中轿车和 SUV 的检测准确率超过 96%,公交车和货车由于体型较大、特征明显,准确率也达到 93% 以上,即使在中度遮挡(如 2-3 辆车部分重叠)情况下,准确率仍保持在 90% 以上,能够为信号灯配时提供准确的车道级车辆数据支撑。
在信号灯配时效果验证中,将基于两级模糊控制的配时策略与传统单级模糊控制、固定配时策略进行对比,选取车辆平均延误时间、车辆平均通行时间、路口通行效率(单位时间内通过路口的车辆数)作为评价指标。在早高峰拥堵场景下,固定配时策略由于无法根据车流量动态调整,车辆平均延误时间为 68.35 秒,平均通行时间为 89.21 秒,通行效率为 125 辆 / 分钟;传统单级模糊控制策略通过单一参数输入调整配时,平均延误时间降至 54.73 秒,平均通行时间降至 71.63 秒,通行效率提升至 148 辆 / 分钟;而基于两级模糊控制的配时策略,由于兼顾了当前相位和下一相位的拥堵强度,平均延误时间进一步降至 41.11 秒,相比单级模糊控制降低 13.62 秒,平均通行时间降至 54.05 秒,相比单级模糊控制减少 17.58 秒,通行效率提升至 172 辆 / 分钟。在晚高峰拥堵场景下,两级模糊控制策略的优势同样明显,平均延误时间和平均通行时间分别比单级模糊控制降低 12.85 秒和 16.32 秒。在平峰和畅通场景下,两级模糊控制策略的平均延误时间和平均通行时间虽不如拥堵场景下降低幅度大,但仍比单级模糊控制和固定配时策略低 5%-8%,且通行效率保持稳定提升,表明该配时策略在不同交通流量场景下均能有效缓解交通拥堵,提升路口通行能力。
import cv2
import numpy as np
import matplotlib.pyplot as plt
from ultralytics import YOLO # 用于YOLOv3车辆检测
import time
# 1. 改进的ViBe算法类实现
class ImprovedViBe:
def __init__(self, num_samples=20, match_threshold=20, update_factor=16):
self.num_samples = num_samples # 每个像素的样本数量
self.match_threshold = match_threshold # 匹配阈值
self.update_factor = update_factor # 初始更新因子
self.background_model = None # 背景模型
self.ghost_threshold = 30 # 鬼影判断阈值
self.var_high = 500 # 高复杂度方差阈值
self.var_low = 200 # 低复杂度方差阈值
# 初始化背景模型(多帧均值去鬼影)
def init_model(self, init_frames):
if len(init_frames) < self.num_samples:
raise ValueError("初始化帧数量不足")
# 计算多帧均值作为鬼影判断基准
mean_frame = np.mean(init_frames, axis=0).astype(np.uint8)
height, width = init_frames[0].shape[:2]
# 初始化背景模型库(HxWxnum_samples)
self.background_model = np.zeros((height, width, self.num_samples), dtype=np.uint8)
for i in range(height):
for j in range(width):
# 从初始化帧中随机选择样本
sample_indices = np.random.choice(len(init_frames), self.num_samples, replace=False)
for k in range(self.num_samples):
pixel_val = init_frames[sample_indices[k]][i, j]
# 鬼影判断:若样本与均值差值过大,替换为均值附近值
if abs(int(pixel_val) - int(mean_frame[i, j])) > self.ghost_threshold:
self.background_model[i, j, k] = mean_frame[i, j] + np.random.randint(-5, 6)
else:
self.background_model[i, j, k] = pixel_val
# 计算像素方差,确定背景复杂度
def calculate_variance(self, i, j):
pixel_samples = self.background_model[i, j, :]
return np.var(pixel_samples)
# 背景更新策略(基于复杂度)
def update_background(self, i, j, pixel_val):
variance = self.calculate_variance(i, j)
# 根据方差确定更新概率
if variance > self.var_high:
update_prob = 1 / 4 # 高复杂度:高更新概率
elif variance < self.var_low:
update_prob = 1 / 32 # 低复杂度:低更新概率
else:
update_prob = 1 / 16 # 中复杂度:中等更新概率
# 随机更新样本
if np.random.random() < update_prob:
idx = np.random.randint(0, self.num_samples)
self.background_model[i, j, idx] = pixel_val
# 邻域更新
if np.random.random() < update_prob:
neighbors = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
ni, nj = i + np.random.choice([n[0] for n in neighbors]), j + np.random.choice([n[1] for n in neighbors])
if 0 <= ni < self.background_model.shape[0] and 0 <= nj < self.background_model.shape[1]:
n_idx = np.random.randint(0, self.num_samples)
self.background_model[ni, nj, n_idx] = pixel_val
# 车辆检测(前景提取)
def detect_foreground(self, frame):
if self.background_model is None:
raise ValueError("背景模型未初始化")
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) if len(frame.shape) == 3 else frame
height, width = gray_frame.shape
foreground_mask = np.zeros((height, width), dtype=np.uint8)
for i in range(height):
for j in range(width):
pixel_val = gray_frame[i, j]
# 计算匹配样本数
matches = np.sum(np.abs(self.background_model[i, j, :] - pixel_val) < self.match_threshold)
if matches < 2: # 匹配数少于2,判定为前景(车辆)
foreground_mask[i, j] = 255
# 前景区域不更新背景
else:
# 背景区域更新背景
self.update_background(i, j, pixel_val)
# 形态学操作去除噪声
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
foreground_mask = cv2.morphologyEx(foreground_mask, cv2.MORPH_OPEN, kernel)
foreground_mask = cv2.morphologyEx(foreground_mask, cv2.MORPH_CLOSE, kernel)
return foreground_mask
# 2. 虚拟线圈车流量统计
class VirtualCoilCounter:
def __init__(self, coil_positions):
self.coil_positions = coil_positions # 线圈位置:[(x1,y1,x2,y2), ...](每个线圈对应一条车道)
self.lane_counts = [0] * len(coil_positions) # 各车道计数
self.previous_states = [False] * len(coil_positions) # 线圈前一状态(是否有车)
# 检测线圈区域是否有车(基于前景掩码)
def check_coil_state(self, foreground_mask, coil_rect):
x1, y1, x2, y2 = coil_rect
coil_region = foreground_mask[y1:y2, x1:x2]
# 线圈区域内前景像素占比超过10%,判定有车
car_pixel_ratio = np.sum(coil_region == 255) / (coil_region.size)
return car_pixel_ratio > 0.1
# 更新车道计数(状态从无车变有车,计数+1)
def update_counts(self, foreground_mask):
</doubaocanvas>

如有问题,可以直接沟通
👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇
更多推荐


所有评论(0)