EmguCV:使用光流在运动中的物体上绘制轮廓?
EmguCV: Draw contour on object in Motion using Optical Flow?
我想在 C# 中进行运动检测(使用 EmguCV 3.0)以移除运动中或前景中的对象以绘制叠加层。
这是我用 Kinect 做的示例测试(因为它是深度相机)
如何开始使用 EmguCV 3.0?
- 我尝试了很多无效的后台删除代码
- OpticalFlow 似乎是一个好的开始,但 EmguCV 3.0 中没有示例
- 如果我找到最大的斑点,我怎样才能找到它的轮廓?
有人可以帮助我开始吗?
编辑:2015 年 6 月 17 日
在 EmguCV3.0.0 RC 中,我没有在包和文档中看到 OpticalFlow:
http://www.emgu.com/wiki/files/3.0.0-rc1/document/html/b72c032d-59ae-c36f-5e00-12f8d621dfb8.htm
只有:DenseOpticalFlow、OpticalFlowDualTVL1 ???
这是一个 AbsDiff 代码:
var grayFrame = frame.Convert<Gray, Byte>();
var motionFrame = grayFrame.AbsDiff(backFrame)
.ThresholdBinary(new Gray(20), new Gray(255))
.Erode(2)
.Dilate(2);
结果:
我不知道如何获得白色的动作?
这是 Blob 代码:
Image<Bgr, Byte> smoothedFrame = new Image<Bgr, byte>(frame.Size);
CvInvoke.GaussianBlur(frame, smoothedFrame, new Size(3, 3), 1); //filter out noises
Mat forgroundMask = new Mat();
fgDetector.Apply(smoothedFrame, forgroundMask);
CvBlobs blobs = new CvBlobs();
blobDetector.Detect(forgroundMask.ToImage<Gray, byte>(), blobs);
blobs.FilterByArea(400, int.MaxValue);
blobTracker.Update(blobs, 1.0, 0, 1);
foreach (var pair in blobs) {
CvBlob b = pair.Value;
CvInvoke.Rectangle(frame, b.BoundingBox, new MCvScalar(255.0, 255.0, 255.0), 2);
}
结果:
为什么会有这么多误报?
这是一个 MOG2 代码:
forgroundDetector.Apply(frame, forgroundMask);
motionHistory.Update(forgroundMask);
var motionMask = GetMotionMask();
Image<Bgr, Byte> motionImage = new Image<Bgr, byte>(motionMask.Size);
CvInvoke.InsertChannel(motionMask, motionImage, 0);
Rectangle[] rects;
using (VectorOfRect boundingRect = new VectorOfRect()) {
motionHistory.GetMotionComponents(segMask, boundingRect);
rects = boundingRect.ToArray();
}
foreach (Rectangle comp in rects) { ...
结果:
如果我select最大的区域我怎样才能得到物体的轮廓?
首先,我可以给你一些示例光流代码。
让oldImage
和newImage
成为保存前一帧和当前帧的变量。在我的代码中,它的类型是 Image<Gray, Byte>
.
// prep containers for x and y vectors
Image<Gray, float> velx = new Image<Gray, float>(newImage.Size);
Image<Gray, float> vely = new Image<Gray, float>(newImage.Size);
// use the Horn and Schunck dense optical flow algorithm.
OpticalFlow.HS(oldImage, newImage, true, velx, vely, 0.1d, new MCvTermCriteria(100));
// color each pixel
Image<Hsv, Byte> coloredMotion = new Image<Hsv, Byte>(newImage.Size);
for (int i = 0; i < coloredMotion.Width; i++)
{
for (int j = 0; j < coloredMotion.Height; j++)
{
// Pull the relevant intensities from the velx and vely matrices
double velxHere = velx[j, i].Intensity;
double velyHere = vely[j, i].Intensity;
// Determine the color (i.e, the angle)
double degrees = Math.Atan(velyHere / velxHere) / Math.PI * 90 + 45;
if (velxHere < 0)
{
degrees += 90;
}
coloredMotion.Data[j, i, 0] = (Byte) degrees;
coloredMotion.Data[j, i, 1] = 255;
// Determine the intensity (i.e, the distance)
double intensity = Math.Sqrt(velxHere * velxHere + velyHere * velyHere) * 10;
coloredMotion.Data[j, i, 2] = (intensity > 255) ? 255 : intensity;
}
}
// coloredMotion is now an image that shows intensity of motion by lightness
// and direction by color.
关于如何去除前景这个更大的问题:
如果我有办法获得静态背景图片,那是最好的开始方式。然后,AbsDiff method and using Erode and Dilate or Gaussian 检测前景以平滑图像,然后使用斑点检测。
对于简单的前景检测,我发现 Optical Flow 处理太多(最大 8fps),而 AbsDiff 方法同样准确但对帧率没有影响。
关于轮廓,如果你只是想找到大小、位置和其他时刻,那么上面AbsDiff教程中的斑点检测似乎就足够了,它使用Image.FindContours(...)
.
如果没有,我将开始查看 CvBlobDetector class as used in this tutorial。有一个内置的 DrawBlob 函数可能会派上用场。
我想在 C# 中进行运动检测(使用 EmguCV 3.0)以移除运动中或前景中的对象以绘制叠加层。
这是我用 Kinect 做的示例测试(因为它是深度相机)
如何开始使用 EmguCV 3.0?
- 我尝试了很多无效的后台删除代码
- OpticalFlow 似乎是一个好的开始,但 EmguCV 3.0 中没有示例
- 如果我找到最大的斑点,我怎样才能找到它的轮廓?
有人可以帮助我开始吗?
编辑:2015 年 6 月 17 日
在 EmguCV3.0.0 RC 中,我没有在包和文档中看到 OpticalFlow: http://www.emgu.com/wiki/files/3.0.0-rc1/document/html/b72c032d-59ae-c36f-5e00-12f8d621dfb8.htm
只有:DenseOpticalFlow、OpticalFlowDualTVL1 ???
这是一个 AbsDiff 代码:
var grayFrame = frame.Convert<Gray, Byte>();
var motionFrame = grayFrame.AbsDiff(backFrame)
.ThresholdBinary(new Gray(20), new Gray(255))
.Erode(2)
.Dilate(2);
结果:
我不知道如何获得白色的动作?
这是 Blob 代码:
Image<Bgr, Byte> smoothedFrame = new Image<Bgr, byte>(frame.Size);
CvInvoke.GaussianBlur(frame, smoothedFrame, new Size(3, 3), 1); //filter out noises
Mat forgroundMask = new Mat();
fgDetector.Apply(smoothedFrame, forgroundMask);
CvBlobs blobs = new CvBlobs();
blobDetector.Detect(forgroundMask.ToImage<Gray, byte>(), blobs);
blobs.FilterByArea(400, int.MaxValue);
blobTracker.Update(blobs, 1.0, 0, 1);
foreach (var pair in blobs) {
CvBlob b = pair.Value;
CvInvoke.Rectangle(frame, b.BoundingBox, new MCvScalar(255.0, 255.0, 255.0), 2);
}
结果:
为什么会有这么多误报?
这是一个 MOG2 代码:
forgroundDetector.Apply(frame, forgroundMask);
motionHistory.Update(forgroundMask);
var motionMask = GetMotionMask();
Image<Bgr, Byte> motionImage = new Image<Bgr, byte>(motionMask.Size);
CvInvoke.InsertChannel(motionMask, motionImage, 0);
Rectangle[] rects;
using (VectorOfRect boundingRect = new VectorOfRect()) {
motionHistory.GetMotionComponents(segMask, boundingRect);
rects = boundingRect.ToArray();
}
foreach (Rectangle comp in rects) { ...
结果:
如果我select最大的区域我怎样才能得到物体的轮廓?
首先,我可以给你一些示例光流代码。
让oldImage
和newImage
成为保存前一帧和当前帧的变量。在我的代码中,它的类型是 Image<Gray, Byte>
.
// prep containers for x and y vectors
Image<Gray, float> velx = new Image<Gray, float>(newImage.Size);
Image<Gray, float> vely = new Image<Gray, float>(newImage.Size);
// use the Horn and Schunck dense optical flow algorithm.
OpticalFlow.HS(oldImage, newImage, true, velx, vely, 0.1d, new MCvTermCriteria(100));
// color each pixel
Image<Hsv, Byte> coloredMotion = new Image<Hsv, Byte>(newImage.Size);
for (int i = 0; i < coloredMotion.Width; i++)
{
for (int j = 0; j < coloredMotion.Height; j++)
{
// Pull the relevant intensities from the velx and vely matrices
double velxHere = velx[j, i].Intensity;
double velyHere = vely[j, i].Intensity;
// Determine the color (i.e, the angle)
double degrees = Math.Atan(velyHere / velxHere) / Math.PI * 90 + 45;
if (velxHere < 0)
{
degrees += 90;
}
coloredMotion.Data[j, i, 0] = (Byte) degrees;
coloredMotion.Data[j, i, 1] = 255;
// Determine the intensity (i.e, the distance)
double intensity = Math.Sqrt(velxHere * velxHere + velyHere * velyHere) * 10;
coloredMotion.Data[j, i, 2] = (intensity > 255) ? 255 : intensity;
}
}
// coloredMotion is now an image that shows intensity of motion by lightness
// and direction by color.
关于如何去除前景这个更大的问题:
如果我有办法获得静态背景图片,那是最好的开始方式。然后,AbsDiff method and using Erode and Dilate or Gaussian 检测前景以平滑图像,然后使用斑点检测。
对于简单的前景检测,我发现 Optical Flow 处理太多(最大 8fps),而 AbsDiff 方法同样准确但对帧率没有影响。
关于轮廓,如果你只是想找到大小、位置和其他时刻,那么上面AbsDiff教程中的斑点检测似乎就足够了,它使用Image.FindContours(...)
.
如果没有,我将开始查看 CvBlobDetector class as used in this tutorial。有一个内置的 DrawBlob 函数可能会派上用场。