使用HAARCASCADE的EMGUCV身体检测

本文关键字:检测 EMGUCV HAARCASCADE 使用 | 更新日期: 2023-09-27 18:33:22

我正在尝试开发一个应用程序,该应用程序可以通过网络摄像头检测一个人的上半身和下半身。我试着看emgu的人脸检测,下载了"haarcascade_upperbody.xml"和"haarcascade_lowerbody.xml"。我试图编写与给定的人脸检测相同的代码

但问题是它不会检测到我的身体,而且它不再是实时的。它延迟了 3 秒?

这是我的代码。我希望有人可以帮助我:

private void ProcessFrame(object sender, EventArgs arg)
    {
        Image<Bgr, Byte> ImageFrame = capture.QueryFrame();
        FittingBox.Image = ImageFrame;
        long detectionTime;
        List<Rectangle> upper = new List<Rectangle>();
        List<Rectangle> lower = new List<Rectangle>();
        Detect(ImageFrame,"haarcascade_upperbody.xml","haarcascade_lowerbody.xml",upper,lower,out detectionTime);
        foreach (Rectangle up in upper)
            ImageFrame.Draw(up, new Bgr(Color.Red), 2);
        foreach (Rectangle low in lower)
            ImageFrame.Draw(low, new Bgr(Color.Blue), 2);
    }

 public static void Detect(Image<Bgr, Byte> image, String upperFileName, String lowerFileName, List<Rectangle> upperbody, List<Rectangle> lowerbody, out long detectionTime)
    {
        Stopwatch watch;
        if (GpuInvoke.HasCuda)
        {
            using (GpuCascadeClassifier upper = new GpuCascadeClassifier(upperFileName))
            using (GpuCascadeClassifier lower = new GpuCascadeClassifier(lowerFileName))
            {
                watch = Stopwatch.StartNew();
                using (GpuImage<Bgr, Byte> gpuImage = new GpuImage<Bgr, byte>(image))
                using (GpuImage<Gray, Byte> gpuGray = gpuImage.Convert<Gray, Byte>())
                {
                    Rectangle[] upperRegion = upper.DetectMultiScale(gpuGray, 1.1, 10, Size.Empty);
                    upperbody.AddRange(upperRegion);
                    foreach (Rectangle f in upperRegion)
                    {
                        using (GpuImage<Gray, Byte> upperImg = gpuGray.GetSubRect(f))
                        {
                            using (GpuImage<Gray, Byte> clone = upperImg.Clone())
                            {
                                Rectangle[] lowerRegion = lower.DetectMultiScale(clone, 1.1, 10, Size.Empty);
                                foreach (Rectangle e in lowerRegion)
                                {
                                    Rectangle lowerRect = e;
                                    lowerRect.Offset(f.X, f.Y);
                                    lowerbody.Add(lowerRect);
                                }
                            }
                        }
                    }
                }
                watch.Stop();
            }
        }
        else
        {
            using (CascadeClassifier upper = new CascadeClassifier(upperFileName))
            using (CascadeClassifier lower = new CascadeClassifier(lowerFileName))
            {
                watch = Stopwatch.StartNew();
                using (Image<Gray, Byte> gray = image.Convert<Gray, Byte>())
                {
                    gray._EqualizeHist();
                    Rectangle[] upperDeteced = upper.DetectMultiScale(
                        gray,
                        1.1,
                        10,
                        new Size(50, 50),
                        Size.Empty);
                    foreach (Rectangle f in upperDeteced)
                    {
                        gray.ROI = f;
                        Rectangle[] lowerDetected = lower.DetectMultiScale(
                            gray,
                            1.1,
                            10,
                            new Size(50, 50),
                            Size.Empty);
                        gray.ROI = Rectangle.Empty;
                        foreach (Rectangle e in lowerDetected)
                        {
                            Rectangle lowerRect = e;
                            lowerRect.Offset(f.X, f.Y);
                            lowerbody.Add(lowerRect);
                        }
                    }
                }
                watch.Stop();
            }
        }
        detectionTime = watch.ElapsedMilliseconds;
    }  

使用HAARCASCADE的EMGUCV身体检测

我认为找到直

立姿势人体的最佳方法是OpenCV附带的行人探测器。你不需要任何培训,因为它已经在HogDescriptor中实现。

有关 emguCV,请参阅此示例。至于你使用级联的代码,我从来没有尝试过这些预先训练的级联,所以我不知道它们被训练了哪种图像。

这是旧的,但时间成本对我来说更感兴趣。

正如你所说

"但解决这两个问题"

  1. 是它不会检测到我的身体和
  2. 它不再是实时的。它延迟了 3 秒?

首先从 #2 开始:

让我们假设 3 秒的意思是应用 haar 级联需要 3 秒。恕我直言和经验,这是由于许多因素。

处理 haar 级联的时间等同于目标对象的大小,包括像素高度和宽度的数量以及使用的参数。

此外,检测多尺度参数将影响性能。 在我相当强大的机器上,我看到 MP4 帧宽度为 1280x720,需要 1.5 秒来处理具有以下设置的图像:

    scaleFactor = 1.07
    minNeighbors = 2 
    minSize = 8,8
    maxSize = 200,200 

"webm"720p 能够在 1 秒内处理相同的设置。 您可以通过使用这些设置来调整分类器以使其更快或更慢。我在屏幕上为我的矿样设置了一些控件,并对其进行了一点调整。

在简单的较小的单个测试jpg图像上,它相当快,如200毫秒。

HOG FindPedestrian.Find 非常快速和准确地在大约 1/10 的 150 毫秒时间内找到整个身体,这几乎足以达到大约 7 fps(每秒帧数(的速度,这在我的 I7(不使用 GPU(上

就您的第一个问题而言:

1>是它不会检测到我的身体吗?

好的,您从 EMGU 示例中借用的代码片段是检测面部内部的眼睛。

  • 眼睛进入脸内。
  • 下半身不在上半身内部。

如果你使用Hog找到身体的相对位置,然后将该图像片段传递给haar Lower and Upper的探测器,则可能会明显更快地响应,而不是扫描整个图像。

我认为您将不得不玩/调整设置才能找到任何东西。

还修复了在上层中找到下层的逻辑。