如何在坐标附近分组

时间:2014-01-09 16:22:33

标签: c# list coordinates points

我的论文是“多项选择考试”,我对如何处理我的问题有一个很大的问题。我在这里得到了一张图片(具体位图),所以你可以看到:

Box Detection using EmguCV

这是带有检测到的盒子的图像,我将对此进行描述:

  • 这是一篇1-50件试卷。每个号码都有一个相应的框(数字的右侧,作为答案的容器)
  • 此图片只是一个示例,检测到的框数可能会有所不同。我的近似值是它包含150-200个检测到的盒子。
  • 每个检测到的盒子都存储在列表(MCvBOX2D)中,其中包含 detectedboxes'大小,中心等
  • 我将这些中心坐标转移到新列表列表(PointF)中心;
  • 图片中的每个框可能包含 3-5个检测到的框。正如您所看到的,图像中的每个框中都有多个检测到的盒子。
  • 我按升序排序了所有检测到的盒子,所以我知道哪个可能是number1,number2等等。

以下是我的一些代码,其中包含了对框的排序。

List<PointF> center = new List<PointF>();
List<PointF> centernew = new List<PointF>();
foreach (MCvBox2D box in lstRectangles)
{
   // this code transfers every center-coordinates of detected boxes 
   // to a new list which is center
    center.Add(new PointF(box.center.X, box.center.Y));
}
// and this one sorts the coordinates in ascending order.
centernew = center.OrderBy(p => p.Y).ThenBy(p => p.X).ToList(); 
  • 我已经完成了排序部分,现在我的问题是,因为在图像的每个框中都有很多检测到的框,我想分组 sortedlist < / strong> 中心坐标,因此我可以删除其他检测到的盒子,并为每个号码只获取一个检测到的盒子。

  • 我知道这很难理解所以我会解释更多。

    假设我的检测到的盒子的分类列表包含前五个中心坐标:

假设这是图像第一个框中每个检测到的盒子的中心坐标。

 center[0] = [ 45.39, 47.6]
 center[1] = [ 65.39, 47.6]
 center[2] = [ 45.40, 47.10]
 center[3] = [ 65.45, 47.25]
 center[4] = [ 46.01, 47.50]

and the 2nd are:

 center[5] = [ 200.39, 47.2]
 center[6] = [ 45.39, 47.2]
 center[7] = [ 45.39, 47.3]
 center[8] = [ 45.39, 47.55]
  • 我的目标是组织列表中所有已排序的检测到的盒子,我必须能够将与其他中心具有接近值的所有中心坐标分组,特别是它们的Y坐标。

4 个答案:

答案 0 :(得分:1)

您可以计算给定点与列表中任何其他点之间的距离。如果距离小于盒子宽度的一半,你可以非常肯定它是同一盒子的一部分。

double threshold = 3.0;  // Make this whatever is appropriate

for (int i = center.Count - 1; i >= 0; --i)
    if (center.Any(p => p != center[i] && Distance(center[i], p) < threshold))
        center.Remove(center[i]);

您可以将此用于Distance()方法:

private double Distance(PointF p1, PointF p2)
{
    double deltaX = Math.Abs(p1.X - p2.X);
    double deltaY = Math.Abs(p1.Y - p2.Y);

    return Math.Sqrt((deltaX * deltaX) + (deltaY * deltaY));
}

答案 1 :(得分:1)

您可以使用Distinct与自定义IEqualityComparer(see MSDN)。

例如,定义一个类:

class BoxEqualityComparer : IEqualityComparer<MCvBox2D>
{
    private static Double Tolerance = 0.01; //set your tolerance here

    public Boolean Equals(MCvBox2D b1, MCvBox2D b2)
    {
        if (CentersAreCloseEnough(b1.Center, b2.Center))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    private Boolean CentersAreCloseEnough(PointF c1, PointF c2)
    {
        return Math.Abs(c1.X - c2.X) < Tolerance && Math.Abs(c1.Y - c2.Y) < Tolerance;
    }

}

然后在代码中使用该方法,如下所示:

var distinctRectangles = lstRectangles.Distinct(new BoxEqualityComparer());

您可以自由地实施CentersAreCloseEnough(PointF c1, PointF c2);你可以使用矢量距离,x和y的绝对距离等等。

答案 2 :(得分:1)

var rand = new Random();
var threshold = 1;
var points = new List<PointF>();

for (int i = 0; i < 20; i++)
{
    points.Add(new PointF((float) rand.NextDouble()*10, (float) rand.NextDouble()*10));
}

Console.WriteLine(points.Count);

for (int i = 0; i < points.Count(); i++)
{
    for (int j = i + 1; j < points.Count(); )
    {
        var pointHere = points[i];
        var pointThere = points[j];

        var vectorX = pointThere.X - pointHere.X;
        var vectorY = pointThere.Y - pointHere.Y;

        var length = Math.Sqrt(Math.Pow(vectorX, 2) + Math.Pow(vectorY, 2));

        if (length <= threshold)
        {
            points.RemoveAt(j);
        }
        else
        {
            j += 1;
        }
    }
}

Console.WriteLine(points.Count);

答案 3 :(得分:-1)

如果您只关心具有Y坐标的位置,请按该数字排序。如果要对两者进行排序,可以同时添加X和Y并使用该数字对它们进行排序。这是我所看到的一个例子。

    for(int i = 0; i < points.length - 1; i++)
    {
        int temp = points[i].x + points[i].y;

        for(int j = i+1; j < points.length; i++)
        {
             int temp2 = point[j].x + points[j].y;

             if(temp2 < temp)
             {
                 Point jugglePoint = points[i];
                 points[i] = points[j];
                 points[j] = jugglePoint;
             }
        }
    }