打印
[RTOS]

【RT-Thread作品秀】基于雅特力AT32的车道线识别模型

[复制链接]
4030|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 muyichuan2012 于 2020-6-27 11:00 编辑


【RT-Thread作品秀】基于雅特力AT32的车道线识别模型

转自21 IC嵌入式操作系统分论坛:https://bbs.21ic.com/icview-2972170-1-1.html

作者:menglingyu (孟令玉)

一、概述

在自动驾驶技术发展的如火如荼的今天,大街上越来越多的车辆装载了基于摄像头或雷达等传感器的驾驶辅助系统。摄像头作为系统中重要的一部分,充当着汽车的“双眼”。在摄像头的基础上,运用图像处理技术,可以实现车道线检测、障碍物及行人识别等功能,进一步实现主动刹车、车道保持等驾驶辅助系统。

通常来说图像处理对芯片性能要求都比较高,但汽车上因为功耗和成本受限,在满足要求的基础上要尽量选择低成本、低功耗的芯片,此次做这个基于雅特力AT32的车道线识别模型,就是想验证一下在软件维度上常用的图像处理算法究竟能压缩到什么地步,能否在单核单片机上满足要求地运行。雅特力AT32采用Cortex-M4内核,主频最高可达240M,相较于嵌入式领域常见的单核单片机来说性能已经很强劲了,但相比于常用的图像处理芯片还是有很大差距的。

二、RT-Thread使用情况概述

该项目基于RT-Thread系统,用到了RT-Thread的串口、线程管理、中断管理、内存分配等部分。在使用过程中发现RT-Thread真的是很方便,各种软件包相当齐全,而且有自己的配置工具env,便于内核裁剪。技术支持也很完善,参考手册中详细介绍了内核和每个组件的使用方法,还给出了例程代码,对新手相当友好。

本项目中所使用的AT32开发板已经移植好了RT-Thread,可以在GitHub上下载RT-Thread的源码,在BSP下就可以看到AT32开发板的工程,这里贴个RT-Thread GitHub源码链接:
https://github.com/RT-Thread/rt-thread.git

三、硬件框架

本项目中的硬件主要就是开发板、摄像头、LCD显示屏以及一个12V 电源。

1.AT_START_F403A开发板
AT32F403A的开发板虽然外设比较简单,但能用的引脚都引了出来,方便开发者自己扩展,该有的串口、USB等都有,还自带了调试器AT-Link,赞一个。另外AT32支持将零等待Flash分配为内置SRAM,默认情况下零等待Flash256K,SRAM96K,当RAM空间不够时,可通过选择字节将零等待Flash中的128K分配给SRAM使用,再加上原有的96K,一共就会有224K SRAM空间,但零等待就只有128K了,如果代码长度大于128K,超出的部分就需要放入非零等待Flash,非零等待的执行速率是零等待的 0.4 倍。本项目中因为图像处理所需要的内存较大,所以配置为224K。具体配置方法如下:

(1)设置选择字节:
使用官方ICP工具(所有相关工具均可在官网下载):设备操作---选择字节---选择 96KB/224KB---应用到设备。

(2)工程配置:在代码工程的board.h中将SRAM大小设置为224


2.摄像头

本次使用的摄像头型号是OV2640广角摄像头,200W像素,某宝直接买的带驱动板的,3.3V供电,正好AT开发板上有3.3V电源输出。摄像头的驱动程序见源码中的ov2640.c和sccb.c。简要介绍一下这款摄像头的使用,通信情况分两种,一种是对寄存器写入指令,这种情况下用的是SCCB协议,和IIC很像但又不同,通常情况下都是用IO直接模拟SCCB协议,我也是采用的这种方法。在初始化对各个寄存器写入值之后,传输图像数据时使用的是DCMI接口,8位数据线,以及帧同步、行同步、像素同步等信号线,但因为AT32不支持DCMI接口,所以也都是用GPIO模拟的。

3.LCD
本项目采用的是3.2寸LCD触摸屏,LCD驱动芯片是ILI9341,通信接口采用16位8080接口,驱动代码是源代码中的LCD.C。触摸屏控制芯片是XPT2046,SPI接口,本次没有用到触摸功能,但源代码中也有触摸屏的驱动touch.c,经过调试没有问题的。
整体的引脚定义如下:标黄的是摄像头所用引脚,标绿的是LCD所用引脚。

四、软件框架说明

本项目软件框架较为简单,主要是:

main主线程初始化外设(串口、摄像头、LCD)->

创建摄像头线程->

开始摄像头线程->

【接收并显示图像->图像处理->显示处理后的图像->重新开始接收图像】(循环)
其中重难点在于图像处理,详细步骤又分为:图像滤波、边缘检测、灰度图像二值化和霍夫变换检测直线。

五、软件模块说明

本项目的软件重点在于图像采集、处理和显示。



1. 图像采集

在图像采集步骤中,使用ov2640摄像头直接输出灰度图像,即YUV422格式的图像,图像处理都以灰度图像为源数据,直接采集灰度图像就省去了之后RGB转灰度图像的步骤,还能节省存储空间。设置ov2640输出YUV422格式图像的指令如下:

        SCCB_WR_Reg(0xFF, 0x00);

        SCCB_WR_Reg(0xDA, 0x01);

2. 图像处理

图像处理过程中主要分以下几个步骤:

(1)滤波

为了消除图像中的尖锐噪点,在图像处理的初始阶段要进行滤波。常见的滤波方式有均值滤波、中值滤波、高斯滤波等。本项目中采用的滤波方式是均值滤波,因为单片机资源和运算速度有限,均值滤波相对来说对性能要求较低。均值滤波以图像略微变得模糊为代价,去除图像中的噪声。详细代码见源码中LaneDetect.c中的以下两个函数:

void Filter(u8 * pic,u16 W,u16 H, u16FilterLength);

unsigned char GetAverageNum(u8 * bArray, intiFilterLen);

(2)边缘检测

边缘检测就是指将图像中亮度梯度变化较大的边缘提取出来,其余信息抹去。图像的边缘中包含了很多有用的信息,准确的边缘提取至关重要。边缘检测通常会用到以下几个算子:Prewitt算子、Sobel算子、Laplace算子等,本次采用的是Sobel算子,Sobel算子提取出来的边缘通常粗大明亮,通常情况下提取边缘后还会加一步非极大值抑制,但这次单片机性能确实有限,权衡之后没有做非极大值抑制。详细代码见源码中LaneDetect.c中的:

void EdgeDetect(unsigned char* pBmpBuf,unsignedchar* pBmpBuf2,int lineByte,int width,int height);

(3)灰度图像二值化

经过边缘检测后,将图像中的边缘信息高亮显示,在此基础上再进行二值化,可进一步将图像中不重要的信息去除,只留下亮度高的边缘。二值化的软件实现较为简单,设置一个阈值,然后将亮度值与阈值进行比较,大于阈值的置为最亮,小于阈值的置为最暗,就可以得到二值化的图像。详细代码见源码中LaneDetect.c中的:

Void Image_YUV2Bitmap(u8*InputImageBuf,u8*OutputImageBuf,int width,int height,u8 threshold);

(4)直线检测

在进行完以上的图像预处理后,就可以开始检测直线了。检测直线用到的是霍夫变换,简要来说就是将图像中的亮点的位置对应到坐标系中的x,y,在笛卡尔直角坐标系中,表示一条直线可以用:y = kx + b,转化为极坐标系,可以用一个点(theta, r)来表示(如下图),且他们之间是一一对应的关系。在这个理论的基础上,我们将过直角坐系上所有点的所有直线都转化成极坐标系中的点,这样如果有两个点在一条直线上,那么转化成极坐标系的点后会就发生重合,处于一条直线上的点越多,极坐标系上该条直线所对应的点的重合次数就越多。我们将直角坐标系上的所有点的所有直线都转化成极坐标系上的点后,找出重合次数最多的点,就是图像中最长的直线。但理论上过一点可以画出无数条直线,我们实际计算过程中可以设置一个分辨率,本项目中设置的是每隔5°画一条直线。

霍夫变换就是指将直角坐标系中的坐标值转化为极坐标系中的theta和r的过程,算式如下:

r=(x*cos(π* theta /180)+y*sin(π* theta /180))(0<theta<180);

经过上面的分析我们可以看出来直线检测的计算量是相当大的,这也是整个流程中最耗时间和内存的一个环节。详细代码见源码中LaneDetect.c中的:

int HoughLineDetect(u8* Imagebuf);

程序中的变量i=x,j=y,p=r,k=theta

3. 图像显示

图像显示相对来说就比较简单了,本次所用的LCD屏幕分辨率是240*320,其中下面的240*160区域用来实时显示摄像头采集到的图像,上面240*160用来显示经过处理和直线检测后的图像。传输给LCD的像素值要是RGB格式,在上面的直线检测步骤中,将检测出来的直线上的点的灰度值置为0x01,在显示的时候,判断图像中的灰度值,如果为0则显示RGB黑色,如果为0xFF则显示RBG白色,如果为0x01则显示RGB红色,这样就能在处理后的图像中将直线用红色标记出来。详细代码见源码中LCD.c中的:

#define ColorCvt(YUV)  (YUV==0 ?BLACK:(YUV==0x01?RED:WHITE))

void LCD_DrawBinImg(u16 x,u16 y,u16 width,u16length,u8 threshold,const unsigned char *p);

六、演示效果

先放几张最终的效果图:

LCD下半部分是摄像头实时拍摄的图像,上半部分是经过处理后的图像,标红的是检测出来的车道线。因为是用电脑播放车道线视频模拟的外界场景,所以拍摄效果不是很好。





演示视频:

https://www.bilibili.com/video/BV1bv41167jj/

七、代码地址

https://github.com/Menglingyu2333/RoadLineDetect_V1.0.git







【RTOS】基于雅特力AT32的车道线识别模型.pdf

755.33 KB

使用特权

评论回复
评论
xu@xupt 2023-9-17 08:35 回复TA
很好的资源,学习啦~~ 
沙发
muyichuan2012|  楼主 | 2020-6-27 10:44 | 只看该作者
感谢作者 孟令玉 ,雅特力科技为您的优秀作品打Call。

使用特权

评论回复
板凳
zeshoufx| | 2020-6-28 08:17 | 只看该作者
谢谢分享,,,,,,,,,,,,,,,,,,,

使用特权

评论回复
地板
jw__liu| | 2024-6-3 08:18 | 只看该作者
mark一个

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

198

主题

1899

帖子

28

粉丝