主要内容

车道检测

本例展示了如何实现fpga的车道标记检测算法。

车道检测是先进驾驶辅助系统(ADAS)的关键处理环节。从视频流中自动检测车道边界在计算上具有挑战性,因此通常需要fpga和gpu等硬件加速器来实现实时性能。

在这个示例模型中,基于fpga的车道候选生成器与基于软件的多项式拟合引擎耦合,以确定车道边界。

下载输入文件

本例使用visionhdl_caltech。Avi文件作为输入。该文件大小约为19 MB。从MathWorks网站下载该文件并解压缩下载的文件。

laneZipFile = matlab.internal.examples.download万博1manbetxSupportFile(“visionhdl_hdlcoder”“caltech_dataset.zip”);[outputFolder,~,~] = fileparts(laneZipFile);解压缩(laneZipFile outputFolder);caltechVideoFile = fullfile(输出文件夹,“caltech_dataset”);目录(caltechVideoFile);

系统概述

LaneDetectionHDL.slx系统如下所示。HDLLaneDetector子系统代表硬件加速部分,swlanefitanoverlay子系统代表基于软件的多项式拟合引擎。在帧到像素块之前,RGB输入被转换为强度颜色空间。

modelname =“LaneDetectionHDL”;open_system (modelname);set_param (modelname“SampleTimeColors”“上”);set_param (modelname“SimulationCommand”“更新”);set_param (modelname“开放”“上”);集(allchild (0)“可见”“关闭”);

HDL车道检测器

HDL车道检测器代表了设计的硬件加速部分。该子系统接收来自前置摄像头源的输入像素流,对视图进行转换,得到鸟瞰图,从转换后的视图中定位车道标候选点,并将其缓冲成向量发送到软件端进行曲线拟合和叠加。

set_param (modelname“SampleTimeColors”“关闭”);open_system ([modelname' / HDLLaneDetector '],“力”);

鸟瞰

鸟瞰视图块将前置摄像头视图转换为鸟瞰视角。在此视图中处理图像简化了下游车道检测算法的处理要求。正面的视角会出现视角失真,导致车道在消失点会聚。通过应用透视反变换来修正透视失真。

逆透视映射(IPM)由以下表达式给出:

$ $(\帽子{x}, {y} \帽子)=圆\离开(\压裂{h_ {11} x + h_ {12} y + h_ {13}} {h_ {31} x + h_ {32} y + h_{33}}, \压裂{h_ {21} x + h_ {22} y + h_ {23}} {h_ {31} x + h_ {32} y + h_{33}} \右)$ $

单应矩阵,h,是由物理相机设置的四个内在参数,即焦距、间距、高度和主点(来自针孔相机模型)。有关更多详细信息,请参阅计算机视觉工具箱™文档。

您可以使用计算机视觉工具箱™估计单应矩阵estgeotform2d函数或图像处理工具箱™fitgeotform2d函数创建projtform2d对象。这些函数需要源帧和鸟瞰帧之间的一组匹配点。源帧点被作为感兴趣的梯形区域的顶点,并且可以扩展到超过源帧限制以捕获更大的区域。对于所示的梯形,点映射为:

$ $ sourcePoints = [c_ {x}, c_ {y}; \ d_ {x}, d_ {y}; \现代{x},现代{y}; \ b_ {x}, b_ {y}] $ $

$$birdsEyePoints = [1,1;\ bAPPL,1;\ 1,bAVL;\ bAPPL,bAVL]$$

在哪里bAPPL而且bAVL分别为每行鸟瞰活动像素和活动视频线。

在FPGA/ASIC硬件上实时直接评估源(正面)到目标(鸟瞰)映射是一个挑战。除法的需求以及从帧缓冲区进行非顺序内存访问的可能性意味着这部分设计的计算需求是巨大的。因此,不是直接实时评估IPM计算,而是执行输入到输出映射的离线分析,并用于预计算映射方案。这是可能的,因为单应性矩阵在工厂校准/安装相机后是固定的,因为相机的位置,高度和间距是固定的。

在这个特殊的例子中,鸟眼输出图像是一个[700x640]维的帧,而正面输入图像是[480x640]维的帧。在下一个前置摄像头输入流进来之前,没有足够的空白来输出完整的鸟眼帧。因此,Birds-Eye视图块在完成当前bird -eye帧的处理之前不会接受任何新的帧数据。

open_system ([modelname' / HDLLaneDetector '],“力”);

线路缓冲和地址计算

从输入到输出的全尺寸投影转换将产生[900x640]的输出图像。这需要将完整的[480x640]输入图像存储在内存中,而源像素位置则使用源位置和单应性矩阵来计算。理想情况下,片内内存应该用于此目的,消除对片外帧缓冲区的要求。

您可以通过使用单应矩阵执行逆行映射来确定芯片上要缓冲的行数。下面的脚本从点映射计算单应矩阵,将其用于逆变换以将源帧行映射到鸟瞰图行。

Source & Birds-Eye Frame参数AVL:活动视频线,APPL:每行活动像素sAVL = 480;sAPPL = 640;鸟眼框架bAVL = 700;bAPPL = 640;
确定单应矩阵%点映射[西北;东北;西南;SE)sourcePoints = [218,196;421196;-629405;1276年,405年);birdsEyePoints = [001,001;640001;001900;640900);估计变换tf = estgeotform2d(sourcePoints,birdsEyePoints,“射影”);%单应矩阵h = tf.T;
在源帧上可视化鸟眼ROIvidObj =视频阅读器(“visionhdl_caltech.avi”);vidFrame = readFrame(vidObj);vidFrameAnnotated = insertShape(vidFrame,“多边形”[sourcePoints (:)...sourcePoints(2,:)) sourcePoints(4,:)...“线宽”5,“颜色”“红色”);vidframeannotations = insertShape(vidFrameAnnotated,“FilledPolygon”...[sourcePoints(1,:) sourcePoints(2,:) sourcePoints(4,:)...: sourcePoints (3)),“线宽”5,“颜色”“红色”“不透明度”, 0.2);图(1);次要情节(2,1,1);imshow (vidFrameAnnotated)标题(“源视频帧”);
确定所需的鸟眼线缓冲深度帧中心的反向行映射x = round(sourcePoints(2,1)-(sourcePoints(2,1)-sourcePoints(1,1))/2));Y = 0 (1,bAVL);ii = 1:1:bAVL [~,Y(ii)] = transformPointsInverse(tf,x,ii);结束numRequiredRows = ceil(Y(0.98*bAVL) - Y(1));
可视化逆行映射次要情节(2,1,2);情节(Y,“HandleVisibility”“关闭”);逆向行映射参照线(0.98 * bAVL,“r”“98%”“LabelHorizontalAlignment”“左”...“HandleVisibility”“关闭”);%行缓冲深度yline (Y (1),“r——”“HandleVisibility”“关闭”) yline (Y (0.98 * bAVL),“r”)标题(“鸟瞰反向行映射”);包含(“输出行”);ylabel (“输入行”);传奇(['行缓冲深度:'num2str (numRequiredRows),“行”],...“位置”“西北”);轴平等的;网格

该图显示了输入线到输出线的映射,揭示了为了生成前700行自上而下的鸟眼输出图像,需要大约50行输入图像。这是使用片上存储器存储的可接受的行数。

车道检测

得到鸟瞰图像后,即可进行实际车道检测。有许多技术可以用于此目的。为了实现一个健壮的实现,在流图像数据上工作良好,并且可以在合理的资源成本下在FPGA/ASIC硬件中实现,本例使用[1]中描述的方法。该算法使用垂直方向的一阶高斯导数滤波核对图像进行全卷积,然后进行子区域处理。

open_system ([modelname“/ HDLLaneDetector / LaneDetection”],“力”);

垂直定向滤波器卷积

紧随输入图像的鸟瞰图之后,输出与用于定位深色背景上的高强度像素条的滤波器进行卷积。内核的宽度为8像素,这与鸟瞰图中出现的线的宽度有关。高度设置为16,这与图像中出现的虚线车道标记的大小有关。由于鸟瞰图像与相机的高度、俯仰等有物理关系,因此图像中车道出现的宽度与道路上的物理测量有本质关系。在不同国家运行车道检测系统时,可能需要更新内核的宽度和高度。

滤镜内核的输出如下所示,使用喷墨色图来突出强度的差异。因为滤波器核是一个一般的,垂直方向的高斯导数,所以有一些来自许多不同区域的响应。然而,对于有车道标志的位置,强烈的积极响应位于强烈的消极响应旁边,这在各个列中是一致的。滤波器输出的这一特性被用于检测算法的下一阶段,以定位有效的候选车道。

车道候选生成

在与高斯导数核卷积后,对输出进行子区域处理,以找到存在车道标记的坐标。每个区域由18行组成,采用乒乓存储方案,以确保数据可以连续地通过子系统。

%看到一样open_system ([modelname' / HDLLaneDetector / LaneDetection / LaneCandidateGeneration '],“力”);

柱状图列数

首先,HistogramColumnCount在18行区域上计算每列中阈值像素的数量。列数高表明该区域中可能存在一个车道。这个计数对正阈值和负阈值图像都执行。正直方图计数偏移,以说明内核宽度。车道候选出现在阳性计数和阴性计数都很高的地方。这利用了前面提到的卷积输出的性质,即正磁道出现在负磁道旁边。

在内部,列计数直方图生成选择18行区域的控制信号,计算列直方图,并在准备好时输出结果。一个乒乓缓冲方案已经就位,它允许一个直方图正在读取,而下一个正在写入。

重叠和相乘

如前所述,当鸟眼图像中出现车道时,卷积结果将产生位于高强度负输出条带旁边的高强度正输出条带。正负列计数直方图定位这些区域。为了放大这些位置,正计数输出被延迟8个时钟周期(与内核宽度相关的内在参数),并且正计数和负计数相乘。这将放大正计数和负计数一致的列,并最小化正计数和负计数不一致的区域。该设计是流水线化的,以确保高吞吐量的操作。

零交叉滤波器

在重叠和叠加子系统的输出,峰值出现在有车道标记的地方。峰值检测算法确定车道标记所在的列。由于数据的信噪比相对较高,本例使用简单的FIR滤波操作,然后进行过零检测。零交叉滤波器是使用DSP系统工具箱中的离散FIR滤波器块实现的。它是流水线的高通量操作。

店铺主道

零交叉滤波器输出然后传递到存储主导车道子系统。该子系统的最大内存为7个条目,每次到达18行的新批时,系统都会重置。因此,每个子区域生成7个潜在的候选车道。在这个子系统中,零交叉滤波器输出被流化,并检查潜在的零交叉。如果确实发生过零,则取过零之前的地址与过零之后的地址之间的差值,以获得峰值大小的测量值。子系统存储最大星等的过零位置。

open_system ([modelname' / HDLLaneDetector / LaneDetection LaneCandidateGeneration / StoreDominantLanes '],“力”);

计算自我通道

车道检测子系统输出7个最可行的车道标志。在许多应用中,我们最感兴趣的是包含车辆行驶的车道的车道标记。通过在设计的硬件端计算所谓的“自我通道”,我们可以通过向处理器发送2个通道而不是7个通道来减少硬件和软件之间的内存带宽。Ego-Lane计算被分成两个子系统。当车辆在车道边界内正确运行时,FirstPassEgoLane子系统假设图像的中心列对应于车道的中间。因此,最接近中心的候选车道被假设为自我车道。离群点去除子系统保持车道标记到中心坐标距离的平均宽度。不在当前宽度公差范围内的车道标志将被拒绝。在设计的后期进行曲线拟合时,早期拒绝车道标记会得到更好的结果。

open_system ([modelname“/ HDLLaneDetector / ComputeEgoLanes”],“力”);

控制接口

最后,计算出的自我车道被发送到CtrlInterface MATLAB函数子系统。该状态机使用四个控制信号输入——enable、hwStart、hwDone和swStart来确定何时开始缓冲,接受新的车道坐标到40x1缓冲区中,最后向软件指示所有40个车道坐标都已被缓冲,因此可以执行车道拟合和叠加。dataReady信号确保软件在所有40个坐标都被缓冲之前不会尝试车道拟合,而swStart信号确保当前的40个坐标集将保持到车道拟合完成为止。

软件车道适合和覆盖

然后,检测到的自我车道被传递到SW车道拟合和叠加子系统,在那里执行鲁棒曲线拟合和叠加。回想一下,鸟眼输出大约每两帧产生一次,而不是每连续一帧。因此,曲线拟合和叠加被放置在一个启用的子系统中,该子系统仅在产生新的自我车道时启用。

open_system ([modelname' / SWLaneFitandOverlay '],“力”);

司机

驱动程序MATLAB函数子系统控制硬件和软件的同步。最初它处于轮询状态,它每帧定时采样dataReady输入,以确定硬件何时缓冲了车道坐标的完整[40x1]向量。一旦发生这种情况,它将转换到软件处理状态,其中swStart和进程输出保持高位。驱动程序一直处于软件处理状态,直到swDone输入值为高。由于流程输出循环回到swDone输入,中间有一个速率转换块,因此有效地为fitlanesanoverlay子系统指定了一个恒定的时间预算,以执行拟合和叠加。当swDone值为高时,驱动程序将转换到同步状态,其中swStart值为低,以向硬件表明处理已经完成。软件和硬件之间的同步是这样的,硬件将保留车道坐标的[40x1]向量,直到swStart信号转换回low。当这种情况发生时,硬件的dataReady输出将转换回低电平。

匹配车道和覆盖

适合车道和覆盖子系统是由驱动程序启用的。它执行必要的算术,以便将多项式拟合到输入处接收的车道坐标数据上,然后将拟合的车道和车道坐标绘制到Birds-Eye图像上。

合适的航线

拟合车道子系统在生成的候选车道上运行基于RANSAC的线路拟合例程。RANSAC是一种迭代算法,它基于所提出的曲线与输入数据之间的距离测量建立一个内线表。在这个子系统的输出端,有一个[3x1]向量,它指定了RANSAC例程找到的多项式系数。

覆盖车道标记

覆盖车道标记子系统执行图像可视化操作。它覆盖了自我车道和曲线发现的车道拟合例程。

open_system ([modelname“/ SWLaneFitandOverlay / FitLanesAndOverlay”],“力”);

模拟结果

该模型包括在仿真结果输出处显示的两个视频显示器。的伯兹显示器显示在车道候选覆盖后,进行多项式拟合并将得到的多项式覆盖到图像上的弯曲视角的输出。的OriginalOverlay显示显示伯兹输出扭曲回原来的透视图。

由于在这个模型中使用的大帧尺寸,模拟可能需要相对较长的时间来完成。如果您有HDL验证器许可证,您可以通过使用FPGA in the Loop直接在硬件中运行HDL车道检测器子系统来加速仿真速度。

HDL代码生成

要检查和生成本例中引用的HDL代码,您必须拥有HDL Coder™许可证。

要生成HDL代码,使用以下命令。

makehdl (“LaneDetectionHDL / HDLLaneDetector”

要生成测试平台,使用以下命令。请注意,由于数据量大,生成测试台架需要很长时间。您可能希望在生成测试台前减少模拟时间。

makehdltb (“LaneDetectionHDL / HDLLaneDetector”

为了更快地模拟测试台架,您可以使用以下命令生成SystemVerilog DPIC测试台架。

makehdltb (“LaneDetectionHDL / HDLLaneDetector”“GenerateSVDPITestBench”“ModelSim”

结论

这个例子让我们深入了解了设计ADAS系统的挑战,特别强调了硬件设计中关键部分的加速。

参考文献

[1] R. K. Satzoda和Mohan M. Trivedi,“基于视觉的车道分析:嵌入式实现的问题和方法探索”,2013年IEEE计算机视觉和模式识别会议。

视频来自加州理工学院车道数据集- Mohamed Aly,“城市街道车道标志的实时检测”,2008年IEEE智能车辆研讨会-已获授权使用。

相关的话题