2014-01-09 2 views
2

У меня есть мой тезис «Проверка множественного выбора экзамена», и у меня есть большая проблема о том, что делать с моей проблемой. Я получил изображение кадра (растровый специально) здесь есть, так что вы можете увидеть:Как сгруппировать близлежащие координаты

Box Detection using EmguCV

Это изображение с detectedbox, я опишу это:

  • Это экзаменационная бумага, 1-50 предметов. каждый номер имеет соответствующее поле (правая сторона номера, который служит в качестве контейнера для ответа)
  • Эти снимки являются всего лишь образцом, количество обнаруженных ящиков может отличаться. Мое приближение состоит в том, что оно содержит 150-200 обнаруженных ящиков.
  • Каждый detectedboxes хранятся в List (MCvBOX2D), который держит их размер detectedboxes', центр и т.д.
  • я передал те координаты центра в новый список список (PointF) центра;
  • В каждой коробке с изображением может быть 3-5 обнаруженных ящиков. так как вы можете видеть, что в каждом из полей из изображения имеется несколько обнаруженных ящиков.
  • Я отсортированы все detectedboxes в порядке возрастания, так что я знаю, который, возможно, будет 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 из центра -координирует, поэтому я мог бы устранить другие обнаруженные ящики и получить только один обнаруженный блок для каждого номера.

  • Я знаю, что это трудно понять, поэтому я объясню больше.

    Скажем, мой SortedList из detectedboxes содержит первые пять центров-координаты, которые являются:

допустим этого являются центр-координаты каждого из detectedboxes из первой коробки изображения.

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] 
  • Моя цель состоит в том, чтобы организовать все отсортированные detectedboxes внутри списка, я должен быть в состоянии сгруппировать все центральные-координаты, которые имеют близкое значение с другим центром, в частности, их Y-координат.
+0

Каким должен быть результат для вашего списка образцов с 9 элементами? – MarcinJuraszek

+0

Моим выходом должно быть только 50 обнаруженных ящиков, что означает 50 центральных координат. Эти 1-я и 2-я группы координат являются координатами, которые являются схожими, но не точными, это центральные координаты ящиков, которые обнаруживают какой-то ящик. – julianconcepcion

ответ

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); 
+0

привет, я получил правильный результат. очень отличный ответ, если я не ошибаюсь, это расстояние между двумя точками? Мне просто интересно, для чего это случайный() код? – julianconcepcion

+0

Только некоторые примеры данных для полного рабочего примера. То, что вам нужно, это длина вектора между центрами ... его грубая сила. Если вы хотите, чтобы «лучшее» решение посмотрело на поиск ближайшего соседа. т. е. сократит количество очков, которые вы должны проверить, и сделайте код намного быстрее. http://www.alglib.net/other/nearestneighbors.php –

-1

Если вас интересуют только положения с координатами Y, просто сортируйте их по этому номеру. Если вы хотите сортировать, вы можете добавить как X, так и Y и использовать их для сортировки. Вот пример того, что я meen.

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; 
      } 
     } 
    } 
+0

@ Katianie- Привет, я уже отсортировал свои очки в порядке возрастания, моя проблема в том, что есть избыточные точки, а не избыточные, потому что они не совсем одинаковы. но они очень похожи. может быть, точка в разнице. Я хочу устранить эти ** совершенно похожие точки ** и сохранить только одну центральную координату. – julianconcepcion

+0

вы можете попытаться принять разницу между каждой точкой, чтобы увидеть, есть ли ее> определенная сумма, и если она хранит ее. Вероятно, это будет аналогичный двойной для цикла – Katianie

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

Вы можете использовать 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 и т. д.

Смежные вопросы