2014-04-04 114 views
0

給定像素值的一維陣列和閾值,尋找純色有界圖像(例如邊界內的圖像)的最有效和最有效的算法是什麼?查找有界圖像的算法

我想起了一對夫婦。 例如: 從圖像尺寸的中間點開始,例如寬度/ 2高度/ 2. 循環遍歷像素,直到您碰到不在閾值內的像素爲止。對所有四面進行此操作並從索引中提取維度。 這個算法的問題在於,如果給出的圖像僅在右側有邊界,並且其寬度小於包含圖像的一半...則這不起作用。

public static Rect GetBounded(this WriteableBitmap wb, int aRGBThreshold) 
{ 
    int[] pixels = wb.Pixels; 
    int width = wb.PixelWidth; 
    int height = wb.PixelHeight; 

    int leftIndex = (height/2) * width; 
    int topIndex = width/2; 
    int rightIndex = (width * (height/2 + 1)) - 1; 
    int bottomIndex = width * height - (width/2); 
    int left = 0, top = 0, right = 0, bottom = 0; 

    int i; 
    for (i = leftIndex; i <= rightIndex; i++) 
    { 
     if (pixels[i] < aRGBThreshold) 
      break; 
     left++; 
    } 
    for (i = topIndex; i <= bottomIndex; i += width) 
    { 
     if (pixels[i] < aRGBThreshold) 
      break; 
     top++; 
    } 
    for (i = rightIndex; i >= leftIndex; i--) 
    { 
     if (pixels[i] < aRGBThreshold) 
      break; 
     right++; 
    } 
    for (i = bottomIndex; i >= topIndex; i -= width) 
    { 
     if (pixels[i] < aRGBThreshold) 
      break; 
     bottom++; 
    } 

    return new Rect(left, top, width - right - left, height - bottom - top); 
} 

public static Rect GetBounded(this WriteableBitmap wb, int aThreshold, int rThreshold, int gThreshold, int bThreshold) 
{ 
    int argbthreshold = (aThreshold << 24) + (rThreshold << 16) + (gThreshold << 8) + bThreshold; 
    return wb.GetBounded(argbthreshold); 
} 

enter image description here

+0

感興趣的對象總是一個矩形,就像你的例子,或者它的形狀是任意的? – ChronoTrigger

+0

@ChronoTrigger這是一個很好的問題(和一個真棒遊戲),我想我應該使約束成爲任意形狀?我不確定我將來可能需要這個任意形狀。對於任意形狀寫/更低效率會更難嗎? –

+0

如果形狀受到限制,則始終可以考慮更適合的算法。檢查我的答案。 – ChronoTrigger

回答

1

在這種情況下,你正在尋找一個矩形(如你的方法和代碼提示),你的做法是很好的。您可以通過執行二進制搜索而不是線性搜索來找到行或列中的第一個和最後一個對象點,從而改進它。這與C++函數std::lower_boundstd::upper_bound(請參閱http://en.cppreference.com/w/cpp/algorithm)類似。如果矩形遠離圖像邊界,這應該會更快。

如果對象可以具有任何形狀,但其組件已連接,則可能最好找到位於對象中的單個像素,並稍後執行flood fill

如果對象可以具有任何形狀並且不需要連接,則必須遍歷整個圖像並保持像素超出閾值的最小和最大行數和列數。我認爲僅從左側掃描行就足夠了,直到找到對象像素爲止,然後從右側開始掃描。如果圖像以行優先順序存儲,則掃描行效率更高。如果它按列主要順序排列,則掃描列。