绪论
随着轨道交通的快速发展,轨道交通所配套的安全预警系统也需要很大的提升。轨道交通密度的增大势必也会带来更多安全问题,例如轨道异物入侵、列车调度、铁轨故障等。轨道异物常常伴有不确定性和突发性,尤其是在列车流量较大的路段,异物入侵轨道区域可能会带来严重的事故。但是,由于安防监视器产业的大力发展,轨道异物入侵问题可以一定程度上通过监视器的全天候监视来解决。只要在容易出现异物入侵的轨道路段安装固定视角监视器进行监视,就可以极大缓解这部分区域的异物入侵所带来的危害,例如由行人、社会车辆经常出现的城市乡镇路口等。
轨道入侵检测算法首先需要解决的问题包括两大类:轨道区域识别与异物检测。轨道区域识别需要实现对轨道区域的标注,在异物出现在轨道区域时需要进行预警,在异物不在轨道区域但是在监视范围内时进行持续跟踪,以防异物随时入侵轨道区域。对于直线轨道,可以借鉴Hough变换方法有效从监视画面中检测出轨道区域,然后再使用图像处理方法对相关区域进行标注。对于异物入侵算法,可以使用三帧差法检测连续帧图像之间的差别,检测出运动目标。最终,在运动目标出现在轨道区域时予以预警,完成对轨道交通危险的处理。
视频预处理
对于固定视角监控采集到的视频,首先需要对视频进行预处理,得到不包含动态目标的背景图像,减少这类非固定目标对轨道区域识别的影响。主要步骤为对帧图像求平均,利用这种方法,图像中的动态目标由于在整个图像序列中只存在于小部分帧,因此该目标的像素值会被大部分帧在目标所在区域的像素点的值所稀释,获得一张只包含静态目标的背景图像。
首先使用OpenCV的read函数读取视频文件,返回一张图像和标志位,该图像即按序列顺序读取视频的帧图像,标志位是该帧图像是否读取成功,通过标志位可以判断是否已经读取完成视频全部帧。由于使用平均法消除动目标求背景图像时,每个像素点会有大量图像像素值相加,如果保持int型可能会导致数值溢出,因此使用astype函数先对图像进行强制转换,由uint8型转为float32型,使其能够存储更大范围的像素值。
完成上述处理流程后,搭配read函数标志位与while循环来累加所有帧图像,累加函数使用cv2.accumulate,累加完成后自动跳出循环,再将累加了所有图像的变量除以读取的视频帧数,即一个完整的平均值求背景法。最后,将该平均图像重新转回uint8型进行存储。
轨道区域识别算法
ROI区域的选择
由于自然场景中包含大量不相关目标,其中很大部分都有直线成分,会对轨道区域的识别造成较大影响,因此需要先在图像中划分ROI(Region of Interest)区域,在ROI区域中识别铁轨可以大大提高识别准确率,排除不相关因素的干扰。
使用cv2.setMouseCallback函数,通过点击图像中的像素点获取像素点的坐标。ROI区域为矩形,选择时只要选择矩形对角线两个端点的像素点坐标即可,可以返回相应的坐标值,通过该坐标值绘制ROI区域。ROI区域的绘制首先在一幅像素值全部为0,与输入视频分辨率相同的图像上,将ROI区域的像素点全部置1,这样就获得一幅二值图。如果要在背景图像上截取ROI区域,将背景图像和该二值图像相与就可以得到只有ROI区域的图像,方便后续处理。
图像边缘检测
在进行边缘检测之前往往还包含一部分预处理流程用以增强图像边缘,本算法这部分的预处理包括灰度转换、直方图均衡化和高斯滤波,都可以直接调用OpenCV实现。灰度值转换使用cv2.cvtColor函数,参数为cv2.COLOR_RGB2GRAY,将原始三通道RGB彩图转换为灰度图。
直方图均衡化
转换为单通道灰度图之后对图像进行直方图均衡化用以增强对比度。对于较常用的8位图像,其图形灰度值的分布是0到255之间的,但是实际图像的像素灰度值却有可能集中在直方图的某一部分,这样会使得图像对比度不高,边缘较差。直方图均衡化通过拉伸像素强度分布范围来增强图像对比度,均衡化后的图像只是近似均匀分布。图像的动态范围扩大了,本质是扩大了量化间隔,而量化级别反而少了,各区域之间有明显的边界。OpenCV使用cv2.equalizeHist函数对灰度图像进行直方图均衡化,对于正常光照条件下的自然场景,经过直方图均衡化后,图像对比度往往会提高,有利于目标边缘的检测。
高斯滤波
最后进行高斯滤波,高斯滤波对整幅图像进行加权平均,每一个像素点的值都是其本身和领域内其他像素值经过加权平均得到的,消除图像中的高斯噪声。高斯滤波的具体操作为:用一个高斯核(也称卷积、模板)扫描图像中的每一个像素,用模板确定的领域内像素的加权平均灰度值去替代模板中心像素点的值。
高斯滤波器是根据高斯函数的形状来选择权值的线性平滑滤波器,对于抑制服从高斯分布的噪声很有效,一维零均值高斯函数如公式3.1所示。
其中,高斯函数的参数Sigma决定了高斯函数的宽度。在图像处理中,常采用二维零均值离散高斯函数作平滑滤波器。二维高斯函数如公式3.2所示。
OpenCV使用cv2.GaussianBlur函数对图像进行高斯滤波处理,需要自行定义高斯核尺寸。
Canny边缘检测
完成以上三个预处理步骤之后可以使Canny边缘检测的准确性进一步提高。
Canny边缘检测算子主要包括下面三个步骤:第一步,计算图像的梯度值和梯度方向,其中采用了一阶偏微分;第二步,对梯度值进行非极大值拟制,保存局部最大梯度值;最后一步采用双阈值方法检测并连接边缘。首先按照Sobel算子的步骤检测梯度:
运用一对卷积阵列(分别作用于x和y方向),如公式3.3。
使用公式3.4和3.5计算梯度幅值和方向
梯度方向一般取这4个可能的角度之一:0度,45度,90度,135度。
Canny边缘检测算法使用cv2.Canny函数,输入图像需要使单通道8位图像,其中高低阈值两个参数需要自己设置,推荐高低阈值比在2:1到3:1之间。
这样,就得到了一张只包含部分目标边缘的二值图,可以看出轨道的直线边缘较为明显,有利于下一步Hough变换检测直线。
Hough变换法检测轨道区域
Hough变换是图像处理中识别几何形状的基本方法之一,该方法运用两个坐标空间之间的变换将一个空间中具有相同形状的曲线或者直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题,优点是对数据的不完全和噪声不敏感。
Hough变换中使用极坐标系来表示直线,即参数极径和极角,如图3.1。
图3.1 极坐标示意图
因此,直线的表达式可用公式3.6表示
对于点(x0,y0),可以将通过这个点的一簇直线统一定义为公式 ,每一对(rθ,θ)都代表一条通过点(x0,y0)的直线
对于每一个定点(x0,y0),在极坐标系对极径极角平面绘出所有通过它的直线,将得到一条正弦曲线,绘制出所有满足r>0和0<θ<2π,如果两个不同点进行上述操作后得到的曲线在极坐标平面相交,意味着它们通过同一条直线,如图3.2。
图3.2 坐标转换完成后的正弦曲线
因此,一条直线能够通过在极坐标平面寻找交于一点的曲线数量来检测,越多的曲线交于一点也就意味着这个交点表示的直线由更多的点组成。一般可以通过设置直线上点的阈值来定义多少条直线交于一点,这样才认为检测到了一条直线。所以,Hough变换是通过追踪图像中每个点对应曲线间的交点,如果交于一点的曲线的数量超过了阈值就可以认为这个交点所代表的参数极径与极角在原图中是一条曲线。
OpenCV中的Hough变换包括以下三种:
本次轨道区域识别采用的Hough变换是累积概率Hough变换,即OpenCV中自带函数cv2.HoughLinesP,该函数需要输入一张二值图和一部分设置参数,其中参数tho是直线以像素(极径)为单位的距离精度,推荐设置为1.0;参数theta是直线以弧度(极角)为单位的角度精度,推荐设置为pi/180,;threshold即交点的阈值,只有交点超过该阈值的直线才会被检测出来;参数mineLineLength是以像素为单位的最小长度,默认为None;参数maxLineGap为同一方向是哪个两条线段判定为一条直线的最大允许间隔,小于此间隔的两条直线会被认为是同一条直线。在直线识别完成后返回检测到的每条直线的起点、终点坐标。
由于在异物入侵算法中需要调用轨道区域的标注图,所以在检测出轨道直线后,还需要对这组直线进行判断,筛选出两条铁轨所在的直线,然后依据直线端点坐标绘制轨道区域进行保存。
检测轨道所在直线的方法采用了斜率均值和线性拟合。通过Hough变换可以检测到多条直线,虽然轨道一般只有两个主线,但是由于角度、光照等外部因素,直线检测算法往往会得到多条直线或者间断的若干条直线,为轨道的检测带来干扰,所以本文算法首先会计算通过Hough变换检测出来地所有直线的斜率平均值,然后再依次计算每条直线斜率和平均斜率的差值,分别选择差值为正、负最大的那两条直线,作为轨道区域,这样可以尽可能增大轨道区域,避免因为轨道区域不完整而造成预警不及时的情况发生。得到两条斜率相差最大的直线之后,考虑到这两条直线有可能并不是连续的直线,如果直接使用这两条直线的端点坐标作为区域绘制的参数,也会出现区域不完整的情况,所以需要使用线性拟合来对这两条直线的参数进行拟合,然后通过拟合出来的参数绘制最终的轨道区域。但是这种方法的问题是不能检测弯曲的轨道,如果检测弯曲的轨道则需要进行多项式拟合,但是多项式的幂次需要人为观察轨道的弯曲情况来设置,无法达到完全的自动化识别。
得到两条直线的端点坐标之后,使用OpenCV的cv2.fillPoly函数来绘制多边形区域,最终再使用cv2.addWeighted函数将这个区域叠加在背景图像上,同时也要将单独的区域图像进行保存,用于下一步的预警程序
运动目标检测与预警算法
三帧差法
目前,传统的动态目标检测方法包括背景减除法、帧差法和光流法。
背景减除法是用当前帧减去背景图像,得到的偏差区域就是变化区域,方法流程如图4.1。
图4.1 背景减除法示意图
背景减除法对背景图像的要求较高,它的精准性会直接影响减除法的效果,如果当前帧图像和背景图像的差别过大,都会造成较大的结果偏差,例如光照变化、气象影响、背景晃动等。
光流是一个空间运动物体在被观测面上的像素运动瞬时速度场,是场景中可见点的三维速度矢量在平面上的投影。这个顺势速度场包含了大量信息,描述了物体的瞬时运动情况,通过这些信息就能知道运动目标的状态。光流法可以对视角运动的视频进行运动目标追踪,可以有效应对视角抖动等因素造成的当前帧与背景图像的变化。但是光流法对目标的灰度值变化要求较高,需要目标的亮度变化在很小的范围内,不适合全天候下的运动目标检测。
而本文所应对的场景是全天候静态视角异物入侵报警,所以帧差法是一种适合本文描述情况的运动目标检测算法。帧差法是对相邻两帧图像相减,如果相减后的图像像素值大于设定的阈值,则认为该点可能存在运动目标,然后统计所有运动像素点组成一个运动区域,分为两帧差法和三帧差法。
两帧差法处理视频时,如果视频中目标的运动速度十分缓慢,则目标变化区域不大,会形成类似于随机噪声的孤立点。为了避免目标丢失,常常采用三帧差法来进行运动目标的检测。三帧差法是将连续两次帧差法的运算结果进行逻辑与运算得到的,所以可实现运动轨迹的累积,可以更好追踪目标。
设fk-1(x,y)、fk(x,y)、fk+1(x,y)是连续的三帧图像。将原始图像转为单通道灰度图像后,用第k帧图像减去k-1帧图像,阈值化后得到差分图像,再用第k+1帧图像减去第k帧图像,阈值化后得到差分图像,然后再将差分图像和进行逻辑与运算,得到三差分图像,如公式4.1、4.2、4.3。
三帧差法结构框图如图4.2。
图4.2 三帧差法示意图
形态学滤波
膨胀
腐蚀和膨胀是一对相反的操作。膨胀是对局部求最大值的操作。从数学角度来讲,膨胀和腐蚀是将图像与核进行卷积的操作。
核可以是任何形状或大小,它拥有一个单独定义出来的参考点,称其为锚点。多数情况下,核是一个小的,中间带有参考点和实心正方形或者圆盘。膨胀是求最大值的操作。核与图像卷积,计算核所覆盖区域的像素点的最大值,并把这个最大值赋给参考点指定的像素,这样就会使图像的高亮区域逐渐增长。
采用OpenCV中的cv2.dilate函数进行膨胀,需要设置的参数为一张二值图、卷积核的尺寸和迭代次数。
腐蚀
腐蚀是膨胀的逆操作,因此它是在卷积核中寻找局部最小值的过程,将核中的最小值填充进锚点。最终使得图像的高亮区域逐渐减少。
腐蚀操作使用OpenCV中的cv2.erode函数,需要的参数和膨胀相同,只是函数内部所进行的操作不同。
检测到运动目标后,在图像中表示为高亮区域,通过cv2.findContours函数在二值图中寻找高亮区域的边缘,并将边缘上像素点的坐标值进行存储。存储轮廓信息后,分别使用cv2.boundingRect函数和cv2.rectangle函数对每个运动区域绘制矩形框,矩形框所标注的即运动目标。
最后一步的预警程序通过判断矩形框和轨道区域是否重合进行。判断方式是矩形框四个顶点在轨道区域图像高亮区域是否重合,如果重合则将矩形框由安全绿色转为危险红色,完成报警操作。
视频处理结果与分析
上节介绍了基于Hough变换的轨道异物入侵检测算法,本节在Ubuntu环境中使用Python3.7,搭配OpenCV4、Numpy等依赖库对一组包含行人的轨道视频进行处理,分析处理结果。在完成视频预处理后得到一张背景图像,首先进行灰度转化与高斯滤波,如图5.1和5.2。
图5.1 背景图像换为单通道灰度图
图5.2 使用尺寸为21的高斯核处理得到的图像
经过以上预处理之后,使用canny算子处理图像得到边缘。这里使用的高阈值为130,低阈值为10,然后再截取ROI,处理结果如图5.3和5.4。
图5.3 使用双阈值分别为10和130的canny算子得到的边缘图像
图5.4 使用自己设定的ROI坐标后截取的图像边缘
从处理结果来看,Canny算子已经可以较为准确地提取图像中轨道的直线边缘了,同时包含了一些枝叶的干扰边缘。经过ROI区域标注后的边缘变得更加准确清晰。此时再通过Hough变换检测直线便可以获得最准确的结果。最后一步使用累积概率Hough变换来检测边缘图像中的直线,所使用参数为rho=1.0,theta=np.pi/180,threshold=50,mineLineLength=150,mineLineGap=20,其他参数采用默认值。
得到的直线再使用斜率法进行排除,选择斜率为正负两条与平均斜率最大的作为轨道直线。然后在对这两条直线进行线性拟合,绘制颜色,得到最终的轨道区域。轨道区域和叠加了轨道区域的背景图像分别如图5.5和图5.6。
图5.5 轨道区域示意图
图5.6 在原始图像中叠加轨道区域
Hough变换在Canny算子得到的边缘图像上的直线非常准确,包含了可以准确描述轨道区域的两条直线。斜率平均法得到了最大的轨道区域,如图所示与原始图像中的轨道区域吻合得很好。至此,轨道识别部分运行完毕,开始通过三帧差法检测运动目标。选取任意三帧图像的三帧差得到的结果,如图5.7。
图5.7 连续的三帧图像经过三帧差法处理后的结果
但是这样的目标不够清晰,可能会造成误判,因此还需要使用膨胀腐蚀进一步优化运动目标轮廓,使其更为清晰可见。膨胀腐蚀都采用了5×5的卷积核,迭代次数都设置为7次,处理结果如图5.8和图5.9.
图5.8 膨胀后的目标轮廓
图5.9 腐蚀后的图像轮廓
经过膨胀的轮廓包含了很多噪声,但是目标的轮廓也变得更为清晰,而腐蚀操作不仅去除了大量噪声,也没有将目标腐蚀掉。这样,再通过轮廓检测函数就可以绘制运动目标的矩形框了,如图5.9。再加上预警程序即最终处理结果,如图5.10,当运动目标进入铁轨区域时会使用红色矩形框来进行预警。
图5.9 运动目标检测结果
图5.10 运动目标进入轨道区域后,矩形框变为红色
从最终结果来看,一旦视频中出现运动目标,算法就会开始追踪并对目标进行标注,此时并不进行报警。而一旦目标进入轨道区域,算法便可以立即将标识框转为红色,以对轨道区域的异物入侵进行预警,提示工作人员前往相关区域进行异物排除。
Python代码随后公布于GitHub,目前用git还不是很熟练,commit、push之后代码不更新,我查好原因上传之后链接贴上来。