2011-10-11 68 views
0

我正在研究圖形應用程序,用戶可以在畫布上繪製任意數量的線(從點A到點B有一定的粗細),矩形或橢圓。計算形狀的繪製圖像中的獨特像素

完成後,我有一組形狀數據表明每個形狀和線條的位置,我需要確定它們作爲研究項目的一部分着色了多少個獨特像素。

我的幼稚算法是爲每個形狀實現bool shape.Contains(x,y),並針對圖像中每個像素的每個繪製形狀調用它以確定該像素是由直線,矩形還是橢圓繪製的。

以另一種方式工作,我可以創建void shape.SetPixels(bool [,] canvas),並將每個形狀設置爲true,它包含每個像素。這是我實際上實現的,並且對於大型數據集來說,它非常緩慢。

我有一種感覺,有一種更直接的方式去從原始形狀數據到我需要的輸出,而不需要檢查每個像素。所以我的問題是,給定一組形狀數據,是否有一個O(n)函數bool [,] IsColored(int x,int y){},它可以比任何一個更直接地生成彩色像素的真/假的矩陣我給出的想法?

+2

如果你畫它呢?由此產生的位圖本質上就是這樣一個矩陣 – harold

+0

O(n)是什麼意思?實現shape.Contains(x,y)併爲每個形狀調用一次是O(n),其中n是形狀的數量。 – jwd

+0

爲什麼不能形狀只返回它包含的像素集? – Magnus

回答

1

你說的兩種方法通常是你的兩個主要選項。根據需要檢查每個像素,或者預先爲快速查找構建某種數據結構。如果你有一個大的畫布,但只有幾個形狀(因此,相對較少的「開」像素),那麼最好記錄任何形狀的任何像素,例如散列。

HashSet<KeyValuePair<int,int>> listOfPixelsHitByAnyShape = new HashSet() 

foreach(Shape s in allShapes) 
{ 
    s.Draw(listOfPixelsHitByAnyShape); // will update listOfPixelsHitByAnyShape 
} 

// Now we can easily query if a pixel is set 
bool isSet = listOfPixelsHitByAnyShape.Contains(new KeyValuePair(10,99)) 

這應該是快速查找,代價是內存和構建HashSet的時間。

但它不會像你的SetPixels(bool[,] canvas)版本一樣快,也不會使用更多的內存(在我們所討論的稀少情況下)。

0

如果你不使用圖形庫,請,請!


如果它是一個圖形應用程序,假設您已經繪製了用戶輸入的內容。你難道不能查詢嗎?您總是可以繪製2個不同的目標,一個用於漂亮的用戶版本,另一個用於查詢(每個對象都是獨特的顏色)。

你想如何處理重疊?


我們說的數據集有多大?渲染應該是「免費的」,因爲可以在用戶在應用程序中繪製時構建位圖。

如果你所做的事情真的很慢,你可以考慮使用GPU繪製和查詢(可能使用奇特的着色器)。

2

避免使用Bitmap.GetPixel方法。這是很慢很慢。如果可能,您可以使用LockBits或類似技術對位圖數據進行低級訪問。

在我的項目之一,我用:

public void LoadFromBitmap(Bitmap bmp) 
    { 
     if (bmp.Width != Width || bmp.Height != Height) 
      throw new ArgumentException("Size missmatch"); 
     unsafe 
     { 
      BitmapData bmpData = null; 
      try 
      { 
       bmpData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 

       for (int y = 0; y < bmpData.Height; y++) 
       { 
        uint* p = (uint*)((byte*)bmpData.Scan0 + y * bmpData.Stride); 
        for (int x = 0; x < bmpData.Width; x++) 
        { 
         this[x, y] = RawColor.FromARGB(*p); 
         p++; 
        } 
       } 
      } 
      finally 
      { 
       if (bmpData != null) 
        bmp.UnlockBits(bmpData); 
      } 
     } 
    } 

https://github.com/CodesInChaos/ChaosUtil/blob/master/Chaos.Image/Pixels.cs

另一種優化正在實施包含陣列的像素池。在我的經驗中,經常在大對象堆上分配對象強調gc。