我目前正在尝试开发一个使用 EmguCV(OpenCV Wrapper)跟踪队列中的人的系统。我首先运行并理解了我下载的 Emgu 包中的 VideoSurveilance 示例。这是我基于示例的代码:
private static void processVideo(string fileName)
{
Capture capture = new Capture(fileName);
MCvFont font = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_SIMPLEX,
1.0, 1.0);
BlobTrackerAuto<Bgr> tracker = new BlobTrackerAuto<Bgr>();
//I'm using a class that I implemented for foreground segmentation
MyForegroundExtractor fgExtractor = new MyForegroundExtractor();
Image<Bgr, Byte> frame = vVideo.QueryFrame();
fgExtractor.initialize(frame);
while (frame != null)
{
Image<Gray, Byte> foreground = fgExtractor.getForegroundImg(frame);
tracker.Process(frame, foreground);
foreach (MCvBlob blob in tracker)
{
if (isPersonSize(blob))
{
frame.Draw((Rectangle)blob, new Bgr(0, 0, 255), 3);
frame.Draw(blob.ID.ToString(), ref font,
Point.Round(blob.Center), new Bgr(255.0, 255.0, 255.0));
}
}
CvInvoke.cvShowImage("window", frame);
CvInvoke.cvWaitKey(1);
frame = capture.QueryFrame();
}
}
上面的代码用于处理 AVI 视频的每一帧,并在场景中每个人周围用红色矩形显示处理后的帧。我不喜欢IBGFGDetector<Bgr>
使用 VideoSurveilance 示例中使用的类得到的结果,所以我尝试使用我自己的前景检测器,使用 Emgu 的函数,例如 CvInvoke.cvRunningAvg()、CvInvoke.cvAbsDiff()、CvInvoke。 cvThreshold() 和 cvErode/cvDilate()。我有几个问题:
- 视频开始时场景中已经有几个人。视频开始时,我没有得到与场景中的人相对应的斑点。
- 有时我“失去”一个人几帧:我在一个人周围画了几秒钟/几帧的红色矩形,它消失了,过了一会儿又用不同的 ID 绘制了。
- 正如您从示例代码中看到的那样,我检查 blob 是否可能是检查其高度和宽度的人(isPersonSize() 方法),并且仅在通过测试的那些中绘制红色矩形。我怎样才能删除那些不是人大小的?
- 我想测量一个人在场景中停留的时间。知道 blob 何时消失的最佳方法是什么?我是否应该将我认为与人相对应的 blob 的 ID 存储在一个数组中,并在每个循环中检查每个 blob 是否仍然存在使用
tracker.GetBlobByID()
? 如果我不处理循环中的每一帧,我认为我会得到更好的结果。我添加了一个计数器变量和一个 if 语句以每 3 帧处理一次:
if (i % 3 == 0) tracker.Process(frame, foreground);
我添加了 if 语句,因为程序执行速度非常慢。但是当我这样做时,我能够追踪我以前无法追踪的人。
总而言之,如果有人更习惯于 OpenCV/EmguCV 帮助我说这是否是使用 BlobTrackerAuto 跟踪人员的好方法,并帮助我解决上述问题,我将非常感激。我觉得我没有利用 EmguCV 可以提供的工具。