衛星画像があり、すべての緑地を取得したいと思います。実際には、bmpから画像をロードし、1つの色と許容値を選択して、写真の緑色の領域である多くのポリゴンを取得する必要があります。C#でこれを行うにはどうすればよいですか?(フライトシミュレーションにはこれが必要です)
3 に答える
最初のステップは、特定のピクセルが領域内にあるかどうかを確認することです。それは非常に簡単だと思います。次に、「オン」または「オフ」のピクセルの領域を作成できます。
次に、ピクセルをポリゴンに変換する必要があります。その方法は、必要な粒度によって異なります。高精度が必要な場合は、マーチングスクエアを使用して、リージョンからポリゴンを取得できます。単純なポリゴンが必要な場合は、境界線をトレースするためのより高度な方法が必要になります。
LockBitsを使用し、各バイトを繰り返します(ピクセル形式に応じて、インデックス付きの画像はパレットを使用するため、許容範囲内のパレットインデックスを取得するには、最初にそれを調べる必要があります-インデックスなし(および1bpp / 16ppgreyscale以外)の場合は、アクセスできますカラーチャンネルを直接-ここでヘルプについてはGDI+FAQを参照してください)。範囲内の各色付きピクセルは、別の画像に直接書き出すことができます(つまり、必要なピクセルのみ-残りは非表示のピクセルで埋められます-アルファ0)-またはコレクションに書き出すことができます。個人的には前者を先にやります。これは非常に高速です(LockBitsを使用する場合)。次に、ピクセルウォーキングアルゴリズムのエッジ検出を使用して「シャード」(必要に応じて不規則なポリゴン)を計算します。AForgeライブラリはここで役立つかもしれません。
うーん。「魔法の杖」アルゴリズムのように聞こえます(その名前のPhotoShop / PSPのコントロールから、1つのピクセルをクリックして、特定の色のしきい値内のすべての隣接するピクセルを選択できます)。
したがって、最初のステップは、ポリゴンの一部である必要がある「緑」として識別されるビットマップ上のピクセルを選択することです。次に、そのポイントから再帰的に左、右、上下に移動し、そのポイントのピクセルが元のピクセルの色から設定したしきい値制限内にあるかどうかをテストできます。ポイントがしきい値内にあり、まだコレクションに含まれていない場合は、ポイントをコレクションに追加し、トラバースを続けます。ポイントが「十分に緑」でない場合、またはすでにマップされている場合は、戻ります。後続の再帰呼び出しが通過できる方向を制限することにより、「バックトラッキング」を制限する方法があります。たとえば、上下左右に移動するために4回電話をかけたとします。「オリジン」から左に移動するコールは、その時点から、左または上に移動するコールのみを行うことができます。
これで、幾何学的な点のセットにほぼ対応するピクセルのセットができました。次に、ポリゴンの境界を定義するこれらのポイントのサブセットを特定する必要があります。これは、これらのポイントの「凸包」の計算として知られています。ウィキペディアには、C#で実装できる多くのアルゴリズムがあります:http://en.wikipedia.org/wiki/Convex_hull_algorithms。
理解するのが最も簡単なのは、おそらくグラハムスキャンです:すべてのポイントをリストに配置して、最初のポイント(A)から開始し、2番目のポイント(B)に線を引き、Bから3番目のポイント(C)への線が「左折」を構成するかどうかを判断します。 AからBの方向から「または「右折」します。「左折」の場合は、BからCに線を引いて曲がり、その線を前と同じようにCからDの線と比較します。 。それが「右折」である場合は、凸包の可能な頂点としてBを忘れ、AからCに描画し、CからDの線が左折であるかどうかを確認します。「右折」が表示されたら、線を定義する3つの点の現在の「中間点」を無視し、代わりに他の2つの点の間の線をトレースします。続けて、最後のポイントからAに戻ってリストをラップします。ポイントが一連のラインを定義するまで、すべてが最後のラインの方向から「左折」します。これは、ポイントのセットの「凸包」であり、NlogN時間内の任意のポイントのリストで実行できます。
「凸包」がまさにそれであることを理解してください。あなたはそれから(星のような)凹形を決して得ることができません。これが重要な場合は、アルゴリズムを微調整して「右折」を許可する必要がありますが、線分が交差しないようにする必要があります。