主要内容

壶穴检测

此示例扩展了使用双边滤波生成卡通图像示例包括计算质心并在检测到的凹坑上叠加质心标记和文本标签。

道路危险或坑洼检测是任何自动驾驶系统的重要组成部分。之前关于自动凹坑检测的工作[1]将凹坑定义为路面中亮度较暗且纹理与周围路面不同的椭圆区域。然后,使用图像处理检测坑洼就变成了在路面图像中找到符合所选标准的区域的任务。你可以使用任意或全部椭圆的形状,暗度或纹理的判据。

要测量椭圆形状,您可以使用投票算法(如霍夫圆)或模板匹配算法,或基于线性代数的方法(如最小二乘拟合)。在图像处理中,通过选择亮度分割值来测量亮度等级是很简单的。纹理可以通过使用FFT等技术计算区域的空间频率来评估。

这个例子使用亮度分割和面积度量,这样就不会检测到较小的缺陷。为了找到缺陷的中心,本设计计算了质心。该模型在缺陷的中心覆盖一个标记,并在图像上覆盖一个文本标签。

下载输入文件

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

potholeZipFile = matlab.internal.examples.download金宝appSupportFile(“visionhdl”“potholes2.zip”);[outputFolder,~,~] = fileparts(potholeZipFile);解压缩(potholeZipFile outputFolder);potholeVideoFile = fullfile(输出文件夹,“potholes2”);目录(potholeVideoFile);

简介

PotHoleHDLDetector.slx系统如下所示。PotHoleHDL子系统包含了坑洞检测器和叠加算法,并支持HDL代码生成。金宝app有四个输入参数控制算法。ProcessorBehavioral子系统将字符映射写入RAM中用作覆盖标签。

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

FPGA子系统概述

PotHoleHDL子系统将输入的RGB视频转换为强度,然后进行双边滤波和边缘检测。梯形掩模子系统选择巷道区域。然后,该设计应用形态闭合,并计算所有潜在凹坑的质心坐标。探测器在每一帧中选择最大的坑,并保存中心坐标。像素流校准器将坐标的时间与输入流匹配。最后,Fiducial31x31和Overlay32x32子系统在框架上应用alpha通道叠加来添加一个坑洞中心标记和一个文本标签。

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

输入参数值

子系统有四个输入参数,可以在系统运行时更改。

梯度强度参数,梯度阈值,控制算法的边缘检测部分。

Cartoon RGB参数更改覆盖的颜色,即基准标记和文本。

“区域阈值”参数设置检测窗口中标记像素的最小数量,以便将其归类为坑洞。如果该值过低,则会检测到线状裂缝和其他不构成道路危险的缺陷。如果它太高,那么只会检测到最大的危险。

最后一个参数Show Raw允许您更轻松地调试系统。它在RGB输入视频和检测器看到的二进制图像之间切换所显示的图像,在其上绘制覆盖。将此参数设置为1以查看检测器的工作情况。

如果只允许在视频帧边界上进行更改,那么所有这些参数都能最好地工作。FrameBoundary子系统只在帧的有效起始处注册参数。

open_system ([modelname“/ PotHoleHDL / FrameBoundary”),“力”);

RGB到强度

该模型分割输入RGB像素流,以便RGB流的副本继续朝向覆盖块。检测器的第一步是将RGB转换为强度。因为RGB的输入数据类型是uint8, RGB转强度块自动选择uint8作为输出数据类型。

双边滤波器

该算法的下一步是减少高频噪声和更小的道路缺陷。有许多方法可以实现这一点,但使用双边滤波器具有保留边缘的优点,同时减少噪声和更小的区域。

双边滤波器块具有邻域大小和两个标准差的参数,一个用于滤波器的空间部分,一个用于滤波器的强度部分。对于这个应用程序,相对较大的9x9邻域就可以很好地工作。该模型使用3和0.75作为标准差。您可以稍后对这些值进行试验。

索贝尔边缘检测

然后,过滤后的图像被发送到Sobel边缘检测块,Sobel边缘检测块发现图像中的边缘,并返回那些比梯度阈值参数更强的边缘。输出为二值图像。在最终的应用程序中,可以根据路况、天气、图像亮度等变量来设置这个阈值。对于这个模型,阈值是PotHoleHDL子系统的输入参数。

梯形的面具

从二值边缘图像中,您需要删除与坑洼检测无关的任何边缘。一个好的策略是使用蒙版,选择一个感兴趣的多边形区域,并使该区域以外的区域为黑色。该模型没有使用普通的ROI块,因为那样会删除稍后用于质心计算和标记的位置上下文。

操作的顺序在这里也很重要,因为如果在边缘检测之前使用掩码,掩码的边缘将成为强线,这将导致探测器出现假阳性。

在输入的视频中,车辆可能遇到坑的区域仅限于它前面的道路和前方的梯形路段。精确的坐标取决于相机安装和镜头。这个示例为区域的左侧顶部、右侧顶部、左侧底部和右侧底部角使用固定坐标。在这个视频中,梯形的顶部和底部不平行所以这不是一个真正的梯形。

掩模由角之间的直线组成,连接左、右和上、下。

Ltc——rtc / \ / \ / \ lbc-------------rbc

这个例子使用了polyfit确定从角到角的直线拟合。为了便于实现,设计调用polyfit以竖直方向为自变量。此使用量计算X = f(y)而不是更常见的Y = f(x).使用polyfit这种方法允许您使用y方向线计数器作为每一行上感兴趣区域的开始(左)和结束(右)的x坐标查找表的输入地址。

查找表通常在FPGA中的BRAM中实现,因此应该使用基于0的寻址来寻址。该模型在lut之前从基于MATLAB 1的寻址转换为基于0的寻址。为了进一步减小查找表的大小,地址被梯形的起始线偏移。为了得到良好的综合结果,在fpga中使用查找表后寄存器来匹配典型的块RAM寄存器。该寄存器还为设计添加了一些适度的流水线。

对于320x180图像:

光栅= [320,180];LTC = [155, 66];LBC = [1,140];RTC = [155, 66];RBC = [285,179];%适合x = f(y)方便的LUT索引Abl = polyfit([lbc(2),ltc(2)],[lbc(1),ltc(1)],1);%左侧Abr = polyfit([rbc(2),rtc(2)],[rbc(1),rtc(1)],1);%右侧leftxstart = max(1、圆(ltc(2):红细胞(2))* abl (1) + abl (2)));rightxend = min(光栅(1)轮((ltc(2):红细胞(2))* abr (1) + abr (2)));起始线= min(ltc(2),rtc(2));Endline = max(lbc(2),rbc(2));%正确到从零开始寻址左txstart =左txstart - 1;Rightxend = Rightxend - 1;Startline = Startline - 1;Endline = Endline - 1;open_system ([modelname“/ PotHoleHDL / TrapezoidalMask”),“力”);

形态学关闭

接下来的设计使用形态学关闭块来删除或关闭小特征。关闭工作首先做膨胀,然后侵蚀,并有助于消除小的特征,不太可能是坑洼。在块掩码上指定一个邻域,该邻域决定要删除的特性的大小。该模型使用5x5的邻域,类似于磁盘,这样小的特征就被封闭了。

重心

质心计算找到活动区域的中心。该设计连续计算每个31x31像素区域中标记区域的质心。它只在检测到的区域大于输入参数时存储中心坐标。这是硬件系统和软件系统之间的一个常见区别:在为fpga设计硬件时,通常更容易连续计算,但只在需要时存储答案,而不是在软件中按需调用函数。

对于质心计算,您需要从图像的区域中计算三件事:水平方向上像素的加权和,垂直方向上的加权和,以及与区域中标记部分的面积对应的所有像素的总体和。Line Buffer选择31x31像素的区域,并每次返回一列。该算法使用列来计算垂直权值和总权值。对于水平权重,设计将这些列组合起来以获得31x31的内核。你可以根据你想要“中心”的意思来选择权重。这个例子使用了15:15所以31x31区域的中心是(0,0)在计算结果中。

当输出无效时,Vision HDL Toolbox块强制输出数据为零,如pixelcontrol总线输出所示。虽然不是严格要求的,但这种行为使测试和调试更加容易。为了实现质心结果的这种行为,模型使用Switch块,并将Constant块设置为0。

由于您希望检测区域的中心相对于整个图像坐标系统,因此将水平和垂直像素计数添加到计算的质心中。

open_system ([modelname“/ PotHoleHDL / Centroid31”),“力”);

open_system ([modelname' / PotHoleHDL / Centroid31 / CentroidKernel '),“力”);

检测并保持

探测器操作的总面积和从质心。探测器本身非常简单:将质心面积值与阈值参数进行比较,找出大于阈值的最大面积。模型逻辑将存储的区域值与当前区域值进行比较,并在输入大于当前存储的值时存储一个新的区域。通过使用>> =可以选择超过阈值最早的值或超过阈值最近的值。该模型存储最新的值,因为后面的值更接近相机和车辆。当检测器存储一个新的获胜区域值时,它还更新与该区域对应的X和Y质心值。然后将这些坐标传递给子系统的对齐和覆盖部分。

要将X、Y和有效指示传递给对齐算法,请将这些值打包成一个23位字。一旦它们与用于覆盖的输入帧及时对齐,模型就会将它们解包。

open_system ([modelname“/ PotHoleHDL / DetectAndHold”),“力”);

像素流校准器

Pixel Stream Aligner块从检测器获取流信息,并将其和原始RGB像素流发送到覆盖子系统。校准器补偿了检测算法前面所有部分增加的处理延迟,而不需要知道这些块的延迟。如果稍后更改邻域大小或添加更多处理,对准器可以进行补偿。如果总延迟超过最大行数参数的像素流校准块,调整参数。

基准的叠加

基准标记是一个正方形的划线,表示为31位定点数字的31个元素数组。这种表示很方便,因为一次读取将返回每行覆盖像素的整个单词。

该图通过将定点数据转换为二进制数据显示了覆盖模式。在此设计中,该图案可以是31x31尺寸内您希望的任何图案。

负载fiducialROM31x31.mat十字线= bin(fiducialROM);十字丝(十字= =' 0 ') =' '%将'0'更改为空格以更好地显示
十字= 31日×31 char数组' 1 ' ' 1 ' ' 1 ' ' 1 '“11111111111111111111111”“1 1 1”“1 1 1”“1 1 1”“1 1 1”“1 1 1”“1 1 1”“1 1 1”“1 1”“1 1”“1 1”“111111111111 111111111111”“1 1”“1 1”“1 1”“1 1 1”“1 1 1”“1 1 1”“1 1 1”“1 1 1”“1 1 1”“1 1 1”“11111111111111111111111”' 1 ' ' 1 ' ' 1 ' ' 1 '

基准覆盖子系统具有水平和垂直计数器,带有一组四个比较器,使用检测区域的中心作为标记区域的中心。标记数据用作打开alpha通道覆盖的二进制开关。alpha值是一个固定的透明参数,在ExpandData子系统中,当二进制Detect信号被解包时,它作为增益应用于该信号。

open_system ([modelname“/ PotHoleHDL / Fiducial31x31”),“力”);

字符叠加

用于屏幕显示的字符字体ROM以类似于上面描述的基准ROM的方式存储数据。每个16位的定点数代表16个连续的水平像素。字符映射是16x16。

由于字符数据通常由CPU以ASCII格式写入,最简单的方法是将字符数据存储在双端口RAM中的8位ASCII地址下。字体ROM存储ASCII字符33("!")到122 ("z")。该设计将地址偏移33。

字体ROM由公共领域的固定宽度字体构造,并进行了一些编辑以提高可读性。与基准标记一样,字符ROM数据用作打开alpha通道覆盖的二进制开关。在ExpandData子系统中,字符alpha值是一个固定的透明参数,在Detect信号解包时作为增益应用于该信号。

让角色形象化B在字体ROM中,以二进制显示。

负载charROM16x16.matletterB = bin(charROM16x16(529:544));%字符数组letterB (letterB = =' 0 ')=' '%删除'0'字符以更好地显示
letterB = 16×16字符数组的“111111111”“11111111111”“111 111年的111 111年的111 111年的111 111年的“1111111111”“111111111”“111 111年的111 111年的111 111年的111 111年的111 1111年的“11111111111”“111111111”
open_system ([modelname“/ PotHoleHDL / Overlay32x32”),“力”);

查看探测器原始图像

当您使用复杂的算法时,查看处理过程中的中间步骤对调试和探索非常有帮助。在这个模型中,您可以设置布尔值显示原始参数为1 (真正的)显示二值图像的形态闭合结果,并将检测结果叠加。为了将二进制图像转换为8位RGB覆盖,模型将二进制值乘以255,并在所有三个颜色通道上使用该值。

HDL代码生成

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

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

makehdl (“PotHoleHDLDetector / PotHoleHDL”

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

makehdltb (“PotHoleHDLDetector / PotHoleHDL”

这个模型中可以在FPGA上实现的部分是帧到像素和像素到帧块之间的部分。这就是名为PotHoleHDL的子系统,它包括检测器的所有元素。

在HDL模拟器中的仿真

现在您已经有了HDL代码,您可以在HDL模拟器中模拟它。自动生成的测试台允许您证明Simulink仿真和HDL仿真匹配。金宝app

FPGA的合成

您还可以在FPGA合成工具(如Xilinx Vivado)中合成生成的HDL代码。在Virtex-7 FPGA (xc7v585tffg1157-1)中,实现了超过150mhz的时钟频率。

利用率报告显示,在这个设计中,双边滤波器、像素流校准器和质心函数消耗了大部分资源。双边滤波器需要最多的dsp。质心实现非常高效,只使用两个dsp。质心计算还需要一个倒数查找表,因此使用大量lut作为内存。

要进一步

这个例子展示了检测凹坑算法的一种可能实现。该设计可以通过以下方式进行扩展:

  • 梯度阈值可以用灰度世界模型从平均亮度计算出来。

  • 梯形口罩块可以通过观察车辆车轮位置并调整口罩倾斜侧面的线性拟合来“操纵”。

  • 探测器可以通过查看相对于周围路面的RGB或强度图像的平均亮度来变得更可靠,因为凹坑的强度通常比周围区域更暗。

  • 凹坑的可视频谱图也可以用来寻找凹坑中特定类型的表面。

  • 在梯形巷道区域,利用平均强度可计算出探测面积阈值。

  • 通过存储前N个响应,而不是只存储检测到的最大响应,可以在一帧中检测到多个凹坑。基准标记子系统需要稍微重新设计,以允许重叠标记。

结论

该模型展示了如何在FPGA中实现凹坑检测算法。该检测器的许多有用部分可以在其他应用程序中重用,例如质心块和基准和字符叠加块。

参考文献

[1]科赫、克里斯蒂安和扬尼斯·布里拉基斯。“沥青路面图像中的坑洼检测。”高级工程信息学25岁,没有。3(2011): 507-15。doi: 10.1016 / j.aei.2011.01.002。

[2]阿曼诺维奇,萨米尔,埃米尔布扎和阿尔文胡塞诺维奇。“用图像处理和光谱聚类检测坑洼”第二届信息技术和计算机网络国际会议(ICTN '13),安塔利亚,土耳其。2013年10月。