目录
最终效果:
bilibili视频演示:
基于Prescan+Matlab-simulink的图像识别红绿灯与自动刹车控制系统
prescan工程文件.pex和matlab.cs在本文末
------------------------全文5762字70图一步一步完成大约耗时3h------------------------
一、场景与任务
使用摄像头数据实现红灯停、绿灯行
场景:
具有一个十字路口,水平方向向左延伸200米。主车停止于左侧,并以一定的油门值T开始往右行驶。主车上安装有摄像头,并能拍摄到红绿灯。十字路口的红绿灯按照一定规律变化(绿灯:G秒、黄灯O秒、红灯R秒),初始情况下是绿灯。
任务:
通过图像处理的方式判断摄像头采集到的图片中是否有红灯,如果检测到红灯,请根据当前的车速和红灯图形大小(半径S个像素,代表距离停止线的远近),做出是否踩刹车的决策,以及刹车力度(B),使得车辆能够在停止线前停下。请不断调整参数,获取一些参数组合(包括T、S、B),使得在红灯亮起后,车辆刚好能够停在停止线前。
二、实现步骤
2.1 场景搭建
搭建一个十字路口,水平方向向左延伸200米,主车停止于左侧,
新建一个工程文件akaxi_work4,开始搭建基础的场景
设置一个十字路口,并且水平方向向左延伸200米,并且为了后续工作的可视化,为场景设置一些基础的建筑物作为参考
随机搭建一条道路如上图所示
(后面为了简化识别到的物体又去除了这些建筑物~)
然后设置viewer:
点击添加一个全局视角的观察者,为后续可视化做准备:
同样的在实验下拉栏选择仿真设置
将仿真时刻改为5,然后build:
然后点击prescan的3D查看器:
就可以看到我们搭建的场景啦~
2.2 车辆设置
【需求】主车停止于左侧,并以一定的油门值T开始往右行驶。主车上安装有摄像头,并能拍摄到红绿灯。
我们在actors中选择我们的奥迪A3作为实验车辆,拖拽到道路最左侧:
然后给车辆安装摄像头:
在Detild选择摄像头并且拖拽到车辆上,这里先不需要设置什么,如果右面有需要再设置就好,点击OK
同样的我们需要给摄像头也设置一个观察者
接下来为了实现车辆以一定的油门值T开始往右行驶,我们需要给车辆设置模型:
点击车辆,鼠标右键选择object configuration
点击dynamic后选择车辆为2D Simple,选择Apply应用,记得重新build哦
可以看到我们车辆停在最右侧了:
接下来我们去到matlab simulink:
点击这个图标
在弹出的matlab界面选择布局为默认
双击我们创建的Akaxi_work4文件夹,进入到工作空间
此界面便是我们的工作空间
双击Akaxi_work4_cs.slx进入simulink(这里初始化需要一点时间)
可以看到simulink出现了我们设置的车辆,双击车辆进入:
可以看到有3个模块,分别是车辆自身的参数,摄像头输出,车辆的动力学模型
为了使车辆以一定的油门值T开始往右行驶,我们添加一个matlab函数:
双击空白处唤起搜索simulink,然后在搜索框输入fun,找到MATLAB Function:
如图:
双击函数模块:
然后在弹出的编程界面写一下代码,这里先给车辆油门一个固定的参数T,并且设置为80,之后都是可以更改的哈:
function my_throttle = my_control(u)
% T 参数为油门参数,my_throttle 为油门参数
T = 80;
my_throttle = T;
end
随后把函数的输出my_throttle和车辆动力学模块的Throttle连接
连接完成后点击Run开始仿真运行:
在弹出的仿真界面,可以看到车辆以我们设置的油门参数T(这里为T=80)在直道上面跑:
并且可以看到摄像头的动态输出:
至此车辆设置部分结束啦~
2.3 红绿灯设置
十字路口的红绿灯按照一定规律变化(绿灯:G秒、黄灯O秒、红灯R秒),初始情况下是绿灯。
在prescan找到红绿灯,拖拽防止在十字路口,一般来说在真实的交通场景在,红绿灯放置位置应该是在车辆行驶方向的十字路口的对侧。
双击红绿灯,拖拽出现的圆圈,将红绿灯的方向调整一下,面对我们的车辆
Build后,在3D viewer看到红绿灯正确放在了十字路口,但是红绿灯并没有亮起来,接下里我们便要打开红绿灯显示,并且还要在simulink编写函数让红绿灯模块按照规律进行显示~
右键红绿灯进行设置
找到lights,将红、黄、绿三个颜色都勾上,Apply应用
此时可以看到红绿灯已经显示
并且在3D viewer也可以看到三颜色,接下来我们去matlab simulink设置红绿灯的显示规律
去到matlab
由于我们在prescan进行了物体的设置并且重新build编译了,所以我们在matlab界面需要重新生成,即点击matlab界面的Regenerate
重新生成后可以看到多出来我们添加的红绿灯,同样双击进入:
可以看到红绿灯的三颜色控制,这里可以参考我的博客对红绿灯进行设置:
首先跟前面一样找到matlab function模块
为了让十字路口的红绿灯按照一定规律变化(绿灯G秒、黄灯O秒、红灯R秒),初始情况下是绿灯,我们接着设置
按照题目要求编写红绿灯函数(绿灯G秒、黄灯O秒、红灯R秒)
function [red, org, gre] = light(clock, G, O, R)
green_time = G;% 绿灯时间参数G
yellow_time = O;% 黄灯时间参数O
red_time = R;% 红灯时间参数R
red = [255,0,0];
org = [255,128,0];
gre = [0,255,0];
circle_time = green_time + yellow_time + red_time; % 一个红绿灯的周期时间
time = mod(clock,circle_time);
% 绿灯时间,并且一开始是绿灯
if time < green_time
red = [0,0,0];
org = [0,0,0];
gre = [0,255,0];
% 黄灯时间
elseif time < green_time + yellow_time
red = [0,0,0];
org = [255,128,0];
gre = [0,0,0];
% 红灯时间
else
red = [255,0,0];
org = [0,0,0];
gre = [0,0,0];
end
end
然后搜索digital clock模块,连接到我们刚刚编写好的函数clock上面
并且双击时钟,设置仿真时间为1/20
然后将红黄绿函数输出接入红绿灯的颜色输入,形成函数控制
然后回到matlab工作空间创建一个脚本akaxi_1.m(目的是定义红绿灯仿真的时间值,即G\O\R值):
% 测试红绿灯时间
% 参数说明
% G 绿灯时间参数
% O 黄灯时间参数
% R 红灯时间参数
G = 1;
O = 1;
R = 200;
这里咱可以设置成更加合理的红绿灯时间参数,为了后续实验控制模块是否能正确识别红灯故此红灯时间设置成200秒了,可以根据实际需求进行更改~
点击运行脚本,让这三个值在matlab工作区有值
然后回到simulink,搜索constant常数模块
然后在value中输入G,选择从matlab工作区引入我们定义的G值(绿灯时间)
并将G常数模块与我们的matlab函数模块连接
同理这样处理O和R,黄灯时间与红灯时间点击仿真运行
可以看到我们的红绿灯正确按照我们的控制逻辑显示(绿灯-黄灯-红灯)啦~~~
2.4 图像识别之红灯检测
通过图像处理的方式判断摄像头采集到的图片中是否有红灯
回到车辆上的谁相同,勾选output image:
Build后可以看到摄像头模块变了:
然后给摄像头的R通道,接上一个输出,并且编写我们的图像识别之红色像素检测模块
function [S, flag] = detectRedPixels(R_frame)
% 输入: R_frame - 当前帧的红色通道数据矩阵
% 输出:
% flag - 检测标志(1=检测到红灯,0=未检测到)
% S - 红色像素数量
% 初始化输出
flag = 0;
S = 0;
% 检查输入是否有效
if isempty(R_frame)
return;
end
% 统计值为255的红色像素数量
S = sum(R_frame(:) == 255);
% 设置检测标志
if S > 0
flag = 1; % 检测到红灯标志
% 注意: 在Simulink中不建议使用disp,会影响实时性能
else
flag = 0; % 未检测到红灯
end
end
点击Run进行仿真
可以看到,越接近红灯,S值越大,检测到的红色像素也越多,满足需求~~
2.5 自动刹车控制模块
【需求】如果检测到红灯,请根据当前的车速和红灯图形大小(S个像素,代表距离停止线的远近),做出是否踩刹车的决策,以及刹车力度(B),使得车辆能够在停止线前停下。请不断调整参数,获取一些参数组合(包括T、S、B),使得在红灯亮起后,车辆刚好能够停在停止线前
最终效果:
接入刹车模块:
编写刹车判断逻辑:
function [T, B] = my_control(S, now_v,dis_x)
% dis_x 车所在位置
if 0<= S && S <=5 % 没有检测到红灯
if dis_x < 100 % 车辆在十字路口红绿灯外,看不到红灯,此时应该踩油门
T = 60;
B = 0;
elseif dis_x >100 % 车辆正在通过十字路口,并且看不到红灯,此时应该刹车
T = 0;
B = 100;
else
T = 0;
B = 100;
end
elseif 5< S % 检测到红灯
if 0< now_v && now_v < 10
T = 0;
B = 80;
else % 速度过快
T = 0;
B = 100;
end
else
T = 0;
B = 100;
end
end
然后连线
2.6 仿真测试
2.6.1 停在停止线前
T = 60
B = 100
点击运行仿真,可以看到车辆在开始踩油门加速,后面检测到红灯后,踩刹车减速,最后在红绿灯前面停下来
2.6.2 刚好停在停止线
T = 70
B = 100
刚好停在十字路口线
2.6.3 超出停止线
T = 80
B = 100
超过十字路口
最终的自动控制刹车模块代码:
function [T, B] = my_control(S, now_v,dis_x)
% dis_x 车所在位置
if 0<= S && S <=5 % 没有检测到红灯
if dis_x < 100 % 车辆在十字路口红绿灯外,看不到红灯,此时应该踩油门
T = 70; % 可以修改这里的油门速度!!
B = 0;
elseif dis_x >100 % 车辆正在通过十字路口,并且看不到红灯,此时应该刹车
T = 0;
B = 100;
else
T = 0;
B = 100;
end
elseif 5< S % 检测到红灯
if 0< now_v && now_v < 10
T = 0;
B = 80;
else % 速度过快
T = 0;
B = 100; % 可以修改这里的刹车速度!!
end
else
T = 0;
B = 100;
end
end
三、更多信息
还有一种思路是在摄像头的R输出端引出一个tofile模块,将输出信息保存到matlab的workspace,然后在matlab的工作空间下创建一个脚本,比如akaxi_2.m,然后在matlab工作空间进行处理最后将结果输出到simulink,但是不推荐采用此方式~
akaxi_2.m
load('red.mat');
frame1 = ans.Data(:,:,200); % 提取第1帧(您原先写的是175帧,这里按您最新代码使用第1帧)
% 统计值为255的像素数量
red_pixel_count = sum(frame1(:) == 255); % 关键统计语句
% 输出结果
if red_pixel_count > 0
flag = 1; % 检测到红灯
disp(['检测到红灯(R=255),数量:', num2str(red_pixel_count), ' 个像素']);
else
flag = 0;
disp('未检测到红灯(R=255)');
end
% 可选:可视化显示红色像素位置(调试用)
if red_pixel_count > 0
figure;
imshow(frame1);
title(['红色像素(R=255)检测结果 - 共 ', num2str(red_pixel_count), ' 个']);
% 标记红色像素位置(仅当像素数<1000时显示,避免图像卡顿)
if red_pixel_count < 1000
[rows, cols] = find(frame1 == 255);
hold on;
plot(cols, rows, 'ro', 'MarkerSize', 5, 'LineWidth', 1);
hold off;
end
end
——————————————————————
⭐prescan工程文件.pex和matlab仿真文件.cs⭐
【金山文档 | WPS云文档】 基于Prescan + Matlabsimulink的图像识别红绿灯与自动刹车控制
https://kdocs.cn/l/ckwcP6yvgoIW
----------------------------------------------------------------------------------------------------
相信读到这里的朋友,一定是坚持且优秀的
给博主一个免费的赞👍吧
扫描二维码进博主交流群,问题交流 | 吹吹水 | 一起变得更加优秀
————————————————
2025.4.23
两江重大卓工院