2014-01-09 74 views
2

我有我的論文「多項選擇檢查檢查器」,我在處理我的問題時遇到了一個大問題。我有一個畫面圖像(位圖專)在這兒,所以你可以看到:如何在座標附近組羣

Box Detection using EmguCV

這與detectedbox的形象,我將描述這一點:

  • 這是一個試卷,1-50項。每個號碼都有一個相應的方框(數字的右側,作爲答案的容器)
  • 這張圖片只是一個樣本,檢測到的方框數量可能會有所不同。我的近似值是它包含150-200個檢測框。
  • 每個detectedboxes存儲在列表(MCvBOX2D)其保持detectedboxes'的大小,中心等
  • 我轉移在一個新的列表表(的PointF)中心的那些中心的座標;
  • 從圖像的每個框中,可能有3-5個檢測框。正如您所看到的,圖像中每個框中有多個檢測框。
  • 我按升序排序的所有detectedboxes,所以我想知道,這將可能是數字1,數字等..

下面是我的一些代碼,其中包含框的排序。

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的 - 協調,所以我可以消除其他檢測到的盒子,並且每個數字只能得到一個檢測盒子。

  • 我知道這很難理解,所以我會解釋更多。

    比方說,我排序列表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箇中心座標。第一組和第二組座標是類似但不精確的座標,它們是檢測到某個方框的方框的中心座標。 – 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

你好,我得到了正確的輸出。非常優秀的答案,如果我沒有誤認爲這是兩點之間的距離?我只是想知道Random()代碼是什麼? – julianconcepcion

+0

只是一個完整的工作示例的一些示例數據。你所追求的是中心之間的矢量長度......儘管它的強大力量。如果你想要一個「更好」的解決方案,請查看最近鄰居搜索。即可以減少必須檢查的點數並使代碼運行得更快。 http://www.alglib.net/other/nearestneighbors.php –

-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; 
      } 
     } 
    } 
+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的絕對距離等。

相關問題