在智能视频监控系统中,遗留物检测是一个很重要的应用,对遗留物的检测基本上都是采取对前景掩膜对应的背景区域不进行更新,这往往又会导致其他的问题,如背景模型的鲁棒性和对环境的适应性等。而且在对遗留物检测中,如果背景中的物体移除,有时又需要对该移除物体对应的背景区域进行更新。这里介绍一种判断物体是遗留还是移除的检测算法,也可以参考论文“moving object detection,tracking and classification
for smart video survleillance”。
对于标注为遗留或移除的前景区域,取其外接矩形对应的对应的背景区域,记为R,然后将该区域向外围扩展,在背景中取一个包含R区域的区域S,计算这两个区域的颜色均值Ar和As,然后求这两个均值的比值,从而进一步判断物体是遗留还是移除。判断准则如下:
如果这两个区域的均值的比值满足上式,则认为该区域是物体移除,需要进一步对该区域对应的背景模型进行更新;否则,就是物体遗留,对该区域对应的背景模型不进行更新。为什么该中判断准则有效呢? 在实际中,场景中的背景趋向于同一化,即同一场景的邻近区域比较相似(在室内的情况更是如此),如果是物体遗留,则会引起场景中背景的较大变化,导致均值的变化,进一步直接影响均值比值的较大变化;而物体的移除,则使得移除物体位置变成场景的本来模样,则其均值与其邻域附近的区域的均值很接近;如此,就可以进一步对场景中的物体遗留和移除进行判断。
实现代码如下:
// 返回2表示遗留,1表示移除 int detectLeftRemove(Mat& background, Rect& rect) { int returnVal = -1; Rect surroundRect; surroundRect.x = std::max(0,rect.x-15); // 外移10个像素 surroundRect.y = std::max(0,rect.y-15); if ( (surroundRect.y+rect.height+30) > background.rows ) surroundRect.height = background.rows- surroundRect.y; else surroundRect.height = rect.height+30; if ( (surroundRect.x+rect.width+30) > background.cols ) surroundRect.width = background.cols- surroundRect.x; else surroundRect.width = rect.width+30; Scalar S1 = mean(background(rect)); Scalar S2 = mean(background(surroundRect)); double dist1 = norm(S1); double dist2 = norm(S2); double ratio = 0.0; if ( dist1>= dist2 ) ratio = dist2/dist1; else ratio = dist1/dist2; if (ratio>=0.85 && ratio<=1.0) // 相近表示离开( Remove ) returnVal = 1; else // 否则表示遗留(Left) returnVal = 2; return returnVal; }
另外,介绍一个实用的矩阵缩放函数:
Rect scale_rect(const Rect& r, float scale) { Point2f m=centerRect(r); float width = r.width * scale; float height = r.height * scale; int x=cvRound(m.x - width/2); int y=cvRound(m.y - height/2); return Rect(x, y, cvRound(width), cvRound(height)); }