【问题标题】:Dividing the blob in Emgu CV在 Emgu CV 中划分 blob
【发布时间】:2012-11-28 07:04:08
【问题描述】:

我正在使用 Emgu CV 2.4.2 并希望执行以下算法:

  1. 获取 blob
  2. 设置 ROI 以加快计算速度
  3. 从 blob 中获取局部最小值的像素位置
  4. 划分 blob
  5. 将边界矩形绘制成分割的斑点

我已完成步骤 1-2 并使用 BGStatModel 提取了 blob。这是我得到的结果:

Blob Picture

我想得到垂直投影中局部最小值的像素位置。得到它之后,我想划分blob并像这样绘制矩形:

vertical projection Picture

我试图通过检查 blob 区域中的每个像素来获取局部最小值的像素位置,但这会使我的应用程序运行非常缓慢。这是我的代码:

Point minPix = new Point(0,0);

//copy the foreground frame
Image<Gray, Byte> foreFrame_copy = foreFrame.Copy();

//find the contour
Contour<Point> contours = foreFrame.FindContours(
    CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
    RETR_TYPE.CV_RETR_EXTERNAL);

//looping every contour
while (contours != null)
{
    double PPixel = contours.Area;
    if (PPixel >= 1400)
    {
        //get the contour width
        WR = contours.BoundingRectangle.Width;
        //divide the contour using estimated pixel position
        Num = Convert.ToInt32(WR / 40);

    if (Num > 1)
    {
        //save the estimated pixel position for ROI in arraylist
        ArrayList XList = new ArrayList();
        for (int i = 1; i <= Num; i++)
        {
            int x = i * WR / Num;
            XList.Add(x);
        }

        //get the estimated pixel position 
        foreach (int pos in Xlist)
        {
            //roiWidth= 10px
            int roiWidth = (pos-5) + (pos+5);
            //roiHeight= 20px
            int roiHeight = 20;

            int pixValue = 0;
            //STEP 2: set the ROI to speed up computation
            foreFrame_copy.ROI = new Rectangle(contours.BoundingRectangle.X, contours.BoundingRectangle.Y, roiWidth, roiHeight);
            for (int i = (pos-5); i < roiWidth; i++)
            {
                for (int j = (pos-5); j < (pos+5); j++)
                {
                    pixValue = foreFrame_copy.Data[i, j, 0];
                    //find the white pixel
                    if (pixValue == 255) {
                        //find the position of minimum pixel
                        if (j < j-1) {
                        minPix.X = i;
                        minPix.Y = j;
                        }
                    }

                }
            }
        }

    }
    //draw the red rectangle
    estimatedFrame.Draw(contours.BoundingRectangle, new Bgr(Color.Red), 1);
    contours = contours.HNext;
}
else
{
    contours = contours.HNext;
}
}
//show frame in framebox
blobBox.Image = foreFrame_copy;
estimatedBox.Image = estimatedFrame;

请帮助我如何使用 Emgu CV 以最快的方式完成第 2-5 步。如果有人详细说明这三个步骤和一些代码,我将不胜感激。

提前致谢, 大卫

【问题讨论】:

  • 从你的图中,看起来“极值点”只是最左边、最右边、最上面和最下面的点。这很容易在线性时间内完成。您可能通过“极值点”表示其他意思,这与我之前的观察不同,也与区域极值无关。你能澄清一下这一步吗?
  • 您正在以正确的方式执行步骤 1 和 2。我不明白您所说的“极端点”是什么意思,从您展示的图片中,这些点只是使用垂直投影并在其上找到局部最小值获得。如果您需要一些帮助,请告诉我们。
  • 您好 mmgp 和 Luca,感谢您的回复。我已经编辑了标题以清楚地说明问题。我所说的极小点是指垂直投影上的局部最小值。您可以从这张图片中看到(绿色圆圈)。我试图通过检查每个像素来得到它,但结果很慢。你能在 emgu cv 中为我提供更快的方法吗?在此先感谢大卫
  • 对我来说还不清楚。我正在查看您的“局部最小像素图片”,但它还不完全有意义。最左边的图像是如何获得的?中间图中的垂直投影是如何得到的?有很多方法可以将左图转换为函数,我看不出你的问题是如何明确的。
  • 感谢mmgp的回复。为了清楚起见,也许您可​​以先阅读paper 的第 34 页(第 2 步)。我发现在我的应用程序中应用垂直投影算法(图 4d - 图 4e)存在问题。你能告诉我如何在 EmguCV 中应用它吗?如果还不清楚,请告诉我 mmgp :)。提前谢谢你,大卫

标签: c# image-processing blob emgucv


【解决方案1】:

好的,现在问题变得更清楚了。我个人同意 mmgp 用户的观点,因为缺乏通用性,您作为参考的论文并不是那么好。它是针对一个非常特殊的场景进行编码的,并且对受控环境进行了一些强有力的假设。

我为您提供了一种计算垂直和水平投影以及绝对最大值点的方法作为一个很好的起点

   private void ComputeProjections(Image<Bgr, byte> inputImage)
    {                        
        Image<Gray, Byte> inputGrayImage = inputImage.Convert<Gray, Byte>();
        Matrix<float> imgMatHorizontal = new Matrix<float>(inputGrayImage.Height, 1, 1);
        Matrix<float> imgMatVertical = new Matrix<float>(1, inputGrayImage.Width, 1);

        inputGrayImage.Reduce<float>(imgMatHorizontal, REDUCE_DIMENSION.SINGLE_COL, REDUCE_TYPE.CV_REDUCE_AVG);
        inputGrayImage.Reduce<float>(imgMatVertical, REDUCE_DIMENSION.SINGLE_ROW, REDUCE_TYPE.CV_REDUCE_AVG);
        double minH, maxH, minV, maxV;
        Point minLocH, maxLocH, minLocV, maxLocV;
        imgMatHorizontal.MinMax(out minH, out maxH, out minLocH, out maxLocH);
        imgMatVertical.MinMax(out minV, out maxV, out minLocV, out maxLocV);

        Image<Gray, Byte> maskProvaH = new Image<Gray, byte>(new Size((int)(maxH - minH + 1), imgMatHorizontal.Rows));
        Image<Gray, Byte> maskProvaV = new Image<Gray, byte>(new Size(imgMatVertical.Cols, (int)(maxV - minV + 1)));

        for (int i = 0; i < imgMatHorizontal.Rows; i++)
            maskProvaH.Draw(new CircleF(new PointF((float)(imgMatHorizontal[i, 0] - minH), i), 1f), new Gray(255), 1);

        for (int i = 0; i < imgMatVertical.Cols; i++)
            maskProvaV.Draw(new CircleF(new PointF(i, (float)(imgMatVertical[0, i] - minV)), 1f), new Gray(255), 1);

        inputImage.Draw(new CircleF(new PointF(minLocV.X, minLocH.Y), 2), new Bgr(Color.Green), 1);
        //imageBoxProjected.Image = inputGrayImage;
        imageBoxHorizProj.Image = maskProvaH;
        //imageBoxVerticProj.Image = maskProvaV;

    }

如果您有兴趣找到参考论文中的局部最大值,您可以开始实现简单的局部最大值搜索,例如(水平投影代码):

List<Point> localMaxima = new List<Point>();
        imgMatHorizontal.MinMax(out minH, out maxH, out minLocH, out maxLocH);

        Image<Gray, Byte> maskProvaH = new Image<Gray, byte>(new Size((int)(maxH - minH + 1), imgMatHorizontal.Rows));
        for (int i = 0; i < imgMatHorizontal.Rows; i++)
            maskProvaH.Draw(new CircleF(new PointF((float)(imgMatHorizontal[i, 0] - minH), i), 1f), new Gray(255), 1);

        //// Absolute Horizontal Projection Maxima Drawing
        //inputGrayImage.Draw(new Cross2DF(new PointF(maxLocH.X, maxLocH.Y), 2, 2), new Gray(255), 2);

        // Local maximas search
        for (int i = imgMatHorizontal.Rows - 2; i > 1; i--)
        {
            float prev = imgMatHorizontal[i + 1, 0];
            float curr = imgMatHorizontal[i, 0];
            float next = imgMatHorizontal[i - 1, 0];
            if (curr >= prev && curr >= next)
                localMaxima.Add(new Point((int)curr, i));
        }

此代码来自我的一个 youtube 演示:

Facial Features Demo using projections

其余步骤非常简单,您可以根据自己的需要进行调整,或者按照论文中的建议遵循一些交叉比率阈值。

【讨论】:

  • 除非我误解了你的局部最大值搜索功能,它也会产生除高原边界之外的所有高原点,即使整个高原不是局部最大值。这是故意的吗?找到区域最大值/最小值的一种有效方法是使用形态重建的正确实现。
  • 正如我所说的局部最大值/最小值搜索它只是开发更复杂的有效方法的起点,就像你建议的那样。看一下论文,当两个人重叠时,可能会有高原点,然后定义适当的边界,我认为有必要使用第一个人头和第二个人头之间的距离(即到局部最大值之间)施加一些条件。
  • @mmgp :我已经在我的系统中实现了 Luca 的方法并且它正在工作。非常感谢你们帮助我:)
猜你喜欢
  • 2011-07-18
  • 2014-03-28
  • 2017-11-22
  • 1970-01-01
  • 1970-01-01
  • 2017-12-21
  • 2011-11-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多