2012-04-10 141 views
0

我有一個衛星圖像,我想要得到所有的綠色區域。 在實踐中,我需要從一個BMP加載圖像,選擇一種顏色和tollerance,並獲得許多多邊形是照片中的綠色區域。 我如何在C#中做到這一點? (我需要這個模擬飛行)將像素轉換爲多邊形

+0

你可能需要一個'for'循環,用'Bitmap.GetPixel'獲取每個像素。 – Matthew 2012-04-10 21:06:41

+1

每當我想到Get/SetPixel時,我都會想到等待......慢代碼... – 2012-04-10 21:13:33

回答

1

嗯。聽起來像是一個「魔術棒」算法(來自PhotoShop/PSP中帶有該名稱的控件,允許您單擊一個像素以選擇某個顏色閾值內的所有相鄰像素)。

因此,第一步是選擇位圖中標識爲「綠色」的像素,該像素應該是您多邊形的一部分。然後,您可以遞歸地從該點上下左右移動,並測試該點上的像素是否在您根據原始像素的顏色設置的閾值範圍內。如果該點在閾值內且不在集合中,則將該點添加到集合中,並繼續遍歷;如果該點不夠「足夠綠色」,或者已經被映射,則返回。可以通過限制後續遞歸調用可以遍歷的方向來限制「回溯」。例如,假設我們打了四個電話,上下左右移動。從「原點」出發的呼叫可以從那一點開始只進行進一步呼叫。

現在你有一組像素,大致對應一組幾何點。然後,您必須確定定義多邊形邊界的這些點的子集。這被稱爲計算這些點的「凸包」,維基百科有很多算法可以用C#實現:http://en.wikipedia.org/wiki/Convex_hull_algorithms

最容易理解的可能是Graham Scan:將所有點排列在列表中,從第一個點(A)開始,向第二個(B)繪製一條線,然後確定從B到第三個點(C)將從A到B的方向構成「左轉」或「右轉」。如果它是「左轉」,則從B畫C到C畫出轉彎,然後將該行與以前的從C到D的行進行比較。如果它是一個「右轉」,那麼忘記B作爲凸包的可能頂點,從A畫到C,然後檢查C到D的行是否是左轉。無論何時你看到一個「右轉彎」,都忽略了定義這些線的三個點的當前「中點」,而是在另外兩個線之間追溯一條線。繼續,從最後一點回到A列表,直到這些點定義了一系列從最後一行的方向開始「左轉」的行。這是一組點的「凸包」,它可以在NlogN時間的任意點上完成。

明白一個「凸包」就是那個;你永遠不會得到一個凹形(如星形)。如果這很重要,則需要對算法進行調整以允許「右轉」,但不允許任何線段穿過。

+0

非常感謝!但使用凸包,我只能得到一個多邊形。我如何獲得更多的多邊形? – 2012-04-11 12:57:51

+0

選取位於該多邊形之外的更多像素並重復整個過程。 – KeithS 2012-04-11 14:00:23

0

那麼,第一步是找出一個給定的像素是否在區域內。我認爲這很簡單。然後,您可以創建「開」或「關」的像素區域。

然後你需要將像素轉換爲多邊形。如何做到這一點取決於你需要的粒度。如果您想要高精度,則可以使用Marching Squares來獲取您所在地區的多邊形。如果你需要簡單的多邊形,你需要一個更高級的方法來跟蹤邊界。

0

使用LockBits並遍歷每個字節(取決於像素格式 - 索引圖像使用調色板,因此您需要首先詢問以獲取容差範圍內的調色板索引 - 對於非索引(和非1bpp/16ppgreyscale )您可以直接訪問顏色通道 - 請參閱GDI FAQ以獲取幫助)。 您範圍內的每個彩色像素可以直接寫出到另一個圖像(即只有你想要的像素 - 其餘的都是不可見的像素 - 阿爾法0) - 或集合中。我個人會先做前者。這非常快(如果您使用LockBits)。然後它使用像素行走算法的邊緣檢測來計算「碎片」(如果你喜歡,不規則的多邊形)。 AForge圖書館可能會幫助你。