搬运一下之前写的博客。
寒假浅浅研究了一下智能车赛中的极端光照和赛道反光的解决方案,记录一点思考。
一般来讲,现在比赛中比较流行的针对不同光照强度的算法是otsu算法(大津法)。这种算法针对不同的光照条件动态设置全局阈值,解决了在宏观上光照条件不同的情况,并且经过前缀和优化和间接采样的otsu,时间上非常快,TC264芯片一般2ms以内可以跑完一张图(好像是)。
但是这个方法但是无法很好解决小范围光照不同的情况。例如在一张图中,前半部分和后半部分光照不同,或者更极端一点,反光的情况,如下图。
原图(反光情况)
OTSU全局处理结果
这种情况下,只用otsu就不太够用。虽然可以通过硬件上增加偏振片来一定程度处理,但是感觉也要在算法上为可能的逆天光照做一点准备。
直方图均衡化
参考文章:https://blog.csdn.net/weixin_43981425/article/details/106884136
这篇文章里写可以考虑将灰度值重新映射,重新分配灰度值,使得直方图均衡。感觉这个思路很有意思,而且实现起来速度会很快。
但是仔细想想我认为不太可行。因为实际上我们要解决的问题的全图光照不均匀,也就意味着部分区域的灰度值和另一些区域的灰度值,虽然一样,但是在不同的区域代表的意义不一样,全图重新分配,实际上并不能解决这个问题。
边缘检测算法:Canny算法等
前几天浅浅研究了一下这些边缘检测算法,感觉是可行的。虽然说全图做卷积这个太为难单片机算力了,但是我认为可以对图片做模糊化,缩小图片大小,对模糊化后结果再跑Canny之类的边缘检测算法,感觉应该是可以承受这个计算的。
网上的思路比较多用sobel算子,但是我针对反光的情况跑了一下,感觉sobel算子不如拉普拉斯算子和Roberts算子。下图是二者的处理结果,是2倍缩略图下处理后再做非极大值抑制的结果。
拉普拉斯算子
Roberts算子
处理了一下感觉仍然不太可行,针对反光处可以看出Roberts算子的边缘已经断开了,拉普拉斯算子的边缘虽然没有断开,已经不太明显了。感觉此类的边缘检测在部分区域极端反光下,比起全局阈值的otsu稍微优秀一点,但是没有显著优势(毕竟做卷积需要花算力,增加处理的时间,并且极端反光效果也只是好一点)。
波函数均匀化
读了一些论文,有一些论文在做OCR的时候,针对全局去算对比度或者亮度的函数,然后做一个变换使得均匀化,我感觉这个思路是可以的,但是智能车赛道上的情况不一样,比起文本识别的时候书页的函数,波动更大(例如,拍到墙壁或者非赛道背景的情况)。如果采用这个思路的话,感觉可以做一个逆透视后只针对地面情况做变换,但是我还没来得及去试一试怎么实现。
分块灰度补偿
这里灰度补偿,意思是针对不同的块,做一个对比度的均匀化。我感觉是可行的。但是很明显有一些问题,就是分块的话可能会使得不同块之间分界变明显。不过在智能车中,实际上我们二值化的目的是为了找到边缘,因此可以做一个动态的灰度补偿,也就是说我们在跟踪边缘的时候同时做跟踪点附近的对比度均匀化。这样感觉是可以的而且因为不是全图,算法耗时也比较低,不过我也还没来得及去试一试怎么实现。
(猜测可能存在的问题:在看的见的赛道末端可能会强行做对比度分割?不过反光赛道起码是都能找得到。)
局部阈值法
在 上海交通大学AuTop战队开源算法讲解(一)二值化的技巧 中提到了类似的局部阈值法,原话是这样的:
对于每个像素点,取它周围一小片区域计算得出一个二值化阈值,并对这个像素进行二值化。参考之前的讲过的大津法,一小片区域的二值化阈值可以通过中位数,平均数或者大津法确定
均值阈值法
在上交开源算法中,采取的是平均数做阈值,这个实现起来不难,但是复杂度其实比较高。
1 | // 上交开源的代码片段 |
假设这个区域大小是的(实际操作中这个值不能太小,太小就没意义了),如果对于每个像素点,都像这种做法一样朴素地用二维遍历计算阈值,假设我们边缘跟踪的像素线条长度是,那做一次搜线复杂度就是。
但是实际上我们可以用滑动窗口优化。因为窗口大小固定,所以在边缘跟踪的时候只需要维护窗口内灰度值的和。如果我们已知上一个像素点的窗口和,假设我们下一个像素点是上移的,那么只需要减去旧窗口下侧边,再加上新窗口上侧边,即可得到新窗口的灰度值和。这样做将二维遍历压缩成一维遍历,做一次搜线复杂度是。
(在校赛的时候我就是这样写的,效果还可以。)
Bernsen算法
或者我们可以不采用平均数,而采用Bernsen算法。Bernsen算法和前面灰度补偿均匀化对比度的思路有点像,针对的是对比度。
参考文章:bernsen算法
朴素的Bernsen中,设以当前像素为中心的w*w窗口内,所有像素的最大值是M,最小值是N,两者的均值T。
如果 (是设置的一个对比度阈值),则当前点P的阈值为。否则说明当前窗口所在区域的灰度级差别较小,那么窗口在目标区或在背景区,若,则当前点灰度值为,否则,当前点灰度值为。S作者最初设为,设为。也可以用其他方法改进,大多数论文采用高斯滤波进行改进。不过因为智能车赛道比较简单,噪声其实也不多,所以我感觉高斯滤波没有什么必要。
在边缘跟踪的时候,动态维护窗口内的灰度值最大值最小值,可以使用单调队列维护,这样做时间复杂度与均值阈值中的方法一致,基本可以不用考虑因此而增加的复杂度。